11/*
2- * Copyright (c) 2017, 2018 , Oracle and/or its affiliates.
2+ * Copyright (c) 2017, 2019 , Oracle and/or its affiliates.
33 * Copyright (c) 2014, Regents of the University of California
44 *
55 * All rights reserved.
2525 */
2626package com .oracle .graal .python .builtins .objects .tuple ;
2727
28+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__ADD__ ;
29+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__BOOL__ ;
30+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__CONTAINS__ ;
31+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__EQ__ ;
32+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__GETITEM__ ;
33+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__GE__ ;
34+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__GT__ ;
35+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__HASH__ ;
36+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__ITER__ ;
37+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__LEN__ ;
38+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__LE__ ;
39+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__LT__ ;
40+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__MUL__ ;
41+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__NE__ ;
2842import static com .oracle .graal .python .nodes .SpecialMethodNames .__REPR__ ;
43+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__RMUL__ ;
2944import static com .oracle .graal .python .runtime .exception .PythonErrorType .TypeError ;
3045
3146import java .math .BigInteger ;
4762import com .oracle .graal .python .builtins .objects .slice .PSlice ;
4863import com .oracle .graal .python .builtins .objects .str .PString ;
4964import com .oracle .graal .python .builtins .objects .tuple .TupleBuiltinsFactory .IndexNodeFactory ;
50- import com .oracle .graal .python .nodes .SpecialMethodNames ;
5165import com .oracle .graal .python .nodes .argument .ReadArgumentNode ;
5266import com .oracle .graal .python .nodes .call .special .LookupAndCallUnaryNode ;
5367import com .oracle .graal .python .nodes .expression .BinaryComparisonNode ;
5670import com .oracle .graal .python .nodes .function .builtins .PythonBinaryBuiltinNode ;
5771import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
5872import com .oracle .graal .python .nodes .truffle .PythonArithmeticTypes ;
73+ import com .oracle .graal .python .nodes .util .CastToJavaLongNode ;
5974import com .oracle .graal .python .runtime .exception .PythonErrorType ;
6075import com .oracle .graal .python .runtime .sequence .storage .SequenceStorage ;
6176import com .oracle .truffle .api .CompilerDirectives ;
@@ -263,7 +278,7 @@ long count(PTuple self, Object value,
263278 }
264279 }
265280
266- @ Builtin (name = SpecialMethodNames . __LEN__ , fixedNumOfPositionalArgs = 1 )
281+ @ Builtin (name = __LEN__ , fixedNumOfPositionalArgs = 1 )
267282 @ GenerateNodeFactory
268283 public abstract static class LenNode extends PythonUnaryBuiltinNode {
269284 @ Specialization
@@ -294,10 +309,11 @@ public String toString(Object item, BuiltinFunctions.ReprNode reprNode) {
294309 @ Specialization
295310 @ TruffleBoundary
296311 public String repr (PTuple self ,
312+ @ Cached ("create()" ) SequenceStorageNodes .LenNode getLen ,
297313 @ Cached ("createNotNormalized()" ) SequenceStorageNodes .GetItemNode getItemNode ,
298314 @ Cached ("createRepr()" ) BuiltinFunctions .ReprNode reprNode ) {
299315 SequenceStorage tupleStore = self .getSequenceStorage ();
300- int len = tupleStore . length ( );
316+ int len = getLen . execute ( tupleStore );
301317 StringBuilder buf = new StringBuilder ();
302318 append (buf , "(" );
303319 for (int i = 0 ; i < len - 1 ; i ++) {
@@ -332,7 +348,7 @@ protected static BuiltinFunctions.ReprNode createRepr() {
332348 }
333349 }
334350
335- @ Builtin (name = SpecialMethodNames . __GETITEM__ , fixedNumOfPositionalArgs = 2 )
351+ @ Builtin (name = __GETITEM__ , fixedNumOfPositionalArgs = 2 )
336352 @ ImportStatic (MathGuards .class )
337353 @ TypeSystemReference (PythonArithmeticTypes .class )
338354 @ GenerateNodeFactory
@@ -363,7 +379,7 @@ protected boolean isPSlice(Object object) {
363379 }
364380 }
365381
366- @ Builtin (name = SpecialMethodNames . __EQ__ , fixedNumOfPositionalArgs = 2 )
382+ @ Builtin (name = __EQ__ , fixedNumOfPositionalArgs = 2 )
367383 @ GenerateNodeFactory
368384 abstract static class EqNode extends PythonBinaryBuiltinNode {
369385
@@ -380,7 +396,7 @@ Object doOther(Object left, Object right) {
380396 }
381397 }
382398
383- @ Builtin (name = SpecialMethodNames . __NE__ , fixedNumOfPositionalArgs = 2 )
399+ @ Builtin (name = __NE__ , fixedNumOfPositionalArgs = 2 )
384400 @ GenerateNodeFactory
385401 abstract static class NeNode extends PythonBinaryBuiltinNode {
386402
@@ -397,7 +413,7 @@ boolean doOther(Object left, Object right) {
397413 }
398414 }
399415
400- @ Builtin (name = SpecialMethodNames . __GE__ , fixedNumOfPositionalArgs = 2 )
416+ @ Builtin (name = __GE__ , fixedNumOfPositionalArgs = 2 )
401417 @ GenerateNodeFactory
402418 abstract static class GeNode extends PythonBinaryBuiltinNode {
403419
@@ -415,7 +431,7 @@ PNotImplemented doOther(Object left, Object right) {
415431
416432 }
417433
418- @ Builtin (name = SpecialMethodNames . __LE__ , fixedNumOfPositionalArgs = 2 )
434+ @ Builtin (name = __LE__ , fixedNumOfPositionalArgs = 2 )
419435 @ GenerateNodeFactory
420436 abstract static class LeNode extends PythonBinaryBuiltinNode {
421437
@@ -433,7 +449,7 @@ PNotImplemented doOther(Object left, Object right) {
433449
434450 }
435451
436- @ Builtin (name = SpecialMethodNames . __GT__ , fixedNumOfPositionalArgs = 2 )
452+ @ Builtin (name = __GT__ , fixedNumOfPositionalArgs = 2 )
437453 @ GenerateNodeFactory
438454 abstract static class GtNode extends PythonBinaryBuiltinNode {
439455
@@ -449,7 +465,7 @@ PNotImplemented doOther(@SuppressWarnings("unused") Object left, @SuppressWarnin
449465 }
450466 }
451467
452- @ Builtin (name = SpecialMethodNames . __LT__ , fixedNumOfPositionalArgs = 2 )
468+ @ Builtin (name = __LT__ , fixedNumOfPositionalArgs = 2 )
453469 @ GenerateNodeFactory
454470 abstract static class LtNode extends PythonBinaryBuiltinNode {
455471 @ Specialization
@@ -464,7 +480,7 @@ PNotImplemented contains(@SuppressWarnings("unused") Object self, @SuppressWarni
464480 }
465481 }
466482
467- @ Builtin (name = SpecialMethodNames . __ADD__ , fixedNumOfPositionalArgs = 2 )
483+ @ Builtin (name = __ADD__ , fixedNumOfPositionalArgs = 2 )
468484 @ GenerateNodeFactory
469485 abstract static class AddNode extends PythonBuiltinNode {
470486 @ Specialization
@@ -480,7 +496,7 @@ Object doGeneric(@SuppressWarnings("unused") Object left, Object right) {
480496 }
481497 }
482498
483- @ Builtin (name = SpecialMethodNames . __MUL__ , fixedNumOfPositionalArgs = 2 )
499+ @ Builtin (name = __MUL__ , fixedNumOfPositionalArgs = 2 )
484500 @ GenerateNodeFactory
485501 abstract static class MulNode extends PythonBuiltinNode {
486502 @ Specialization
@@ -490,12 +506,12 @@ PTuple mul(PTuple left, Object right,
490506 }
491507 }
492508
493- @ Builtin (name = SpecialMethodNames . __RMUL__ , fixedNumOfPositionalArgs = 2 )
509+ @ Builtin (name = __RMUL__ , fixedNumOfPositionalArgs = 2 )
494510 @ GenerateNodeFactory
495511 abstract static class RMulNode extends MulNode {
496512 }
497513
498- @ Builtin (name = SpecialMethodNames . __CONTAINS__ , fixedNumOfPositionalArgs = 2 )
514+ @ Builtin (name = __CONTAINS__ , fixedNumOfPositionalArgs = 2 )
499515 @ GenerateNodeFactory
500516 abstract static class ContainsNode extends PythonBinaryBuiltinNode {
501517 @ Specialization
@@ -506,7 +522,7 @@ boolean contains(PTuple self, Object other,
506522
507523 }
508524
509- @ Builtin (name = SpecialMethodNames . __BOOL__ , fixedNumOfPositionalArgs = 1 )
525+ @ Builtin (name = __BOOL__ , fixedNumOfPositionalArgs = 1 )
510526 @ GenerateNodeFactory
511527 public abstract static class BoolNode extends PythonUnaryBuiltinNode {
512528 @ Specialization
@@ -521,7 +537,7 @@ Object toBoolean(@SuppressWarnings("unused") Object self) {
521537 }
522538 }
523539
524- @ Builtin (name = SpecialMethodNames . __ITER__ , fixedNumOfPositionalArgs = 1 )
540+ @ Builtin (name = __ITER__ , fixedNumOfPositionalArgs = 1 )
525541 @ GenerateNodeFactory
526542 public abstract static class IterNode extends PythonUnaryBuiltinNode {
527543 @ Specialization
@@ -534,4 +550,50 @@ Object doGeneric(@SuppressWarnings("unused") Object self) {
534550 return PNotImplemented .NOT_IMPLEMENTED ;
535551 }
536552 }
553+
554+ @ Builtin (name = __HASH__ , fixedNumOfPositionalArgs = 1 )
555+ @ GenerateNodeFactory
556+ public abstract static class HashNode extends PythonUnaryBuiltinNode {
557+ @ Specialization
558+ public long tupleHash (PTuple self ,
559+ @ Cached ("create()" ) SequenceStorageNodes .LenNode getLen ,
560+ @ Cached ("createNotNormalized()" ) SequenceStorageNodes .GetItemNode getItemNode ,
561+ @ Cached ("create(__HASH__)" ) LookupAndCallUnaryNode lookupHashAttributeNode ,
562+ @ Cached ("create()" ) BuiltinFunctions .IsInstanceNode isInstanceNode ,
563+ @ Cached ("createLossy()" ) CastToJavaLongNode castToLongNode ) {
564+ // adapted from https://github.com/python/cpython/blob/v3.6.5/Objects/tupleobject.c#L345
565+ SequenceStorage tupleStore = self .getSequenceStorage ();
566+ int len = getLen .execute (tupleStore );
567+ long multiplier = 0xf4243 ;
568+ long x = 0x345678 ;
569+ long y ;
570+ for (int i = 0 ; i < len ; i ++) {
571+ Object item = getItemNode .execute (tupleStore , i );
572+ Object hashValue = lookupHashAttributeNode .executeObject (item );
573+ if (!isInstanceNode .executeWith (hashValue , getBuiltinPythonClass (PythonBuiltinClassType .PInt ))) {
574+ throw raise (PythonErrorType .TypeError , "__hash__ method should return an integer" );
575+ }
576+ y = castToLongNode .execute (hashValue );
577+ if (y == -1 ) {
578+ return -1 ;
579+ }
580+
581+ x = (x ^ y ) * multiplier ;
582+ multiplier += 82520 + len + len ;
583+ }
584+
585+ x += 97531 ;
586+
587+ if (x == Long .MAX_VALUE ) {
588+ x = -2 ;
589+ }
590+
591+ return x ;
592+ }
593+
594+ @ Fallback
595+ Object genericHash (@ SuppressWarnings ("unused" ) Object self ) {
596+ return PNotImplemented .NOT_IMPLEMENTED ;
597+ }
598+ }
537599}
0 commit comments