this repo has no description
at trunk 9801 lines 315 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "interpreter.h" 3 4#include <memory> 5 6#include "benchmark/benchmark.h" 7#include "gtest/gtest.h" 8 9#include "attributedict.h" 10#include "builtins-module.h" 11#include "bytecode.h" 12#include "compile-utils.h" 13#include "dict-builtins.h" 14#include "handles.h" 15#include "ic.h" 16#include "list-builtins.h" 17#include "module-builtins.h" 18#include "modules.h" 19#include "object-builtins.h" 20#include "objects.h" 21#include "runtime.h" 22#include "str-builtins.h" 23#include "test-utils.h" 24#include "trampolines.h" 25#include "type-builtins.h" 26 27namespace py { 28namespace testing { 29 30using InterpreterDeathTest = RuntimeFixture; 31using InterpreterTest = RuntimeFixture; 32using JitTest = RuntimeFixture; 33 34TEST_F(InterpreterTest, IsTrueBool) { 35 HandleScope scope(thread_); 36 37 Object true_value(&scope, Bool::trueObj()); 38 EXPECT_EQ(Interpreter::isTrue(thread_, *true_value), Bool::trueObj()); 39 40 Object false_object(&scope, Bool::falseObj()); 41 EXPECT_EQ(Interpreter::isTrue(thread_, *false_object), Bool::falseObj()); 42} 43 44TEST_F(InterpreterTest, IsTrueInt) { 45 HandleScope scope(thread_); 46 47 Object true_value(&scope, runtime_->newInt(1234)); 48 EXPECT_EQ(Interpreter::isTrue(thread_, *true_value), Bool::trueObj()); 49 50 Object false_value(&scope, runtime_->newInt(0)); 51 EXPECT_EQ(Interpreter::isTrue(thread_, *false_value), Bool::falseObj()); 52} 53 54TEST_F(InterpreterTest, IsTrueWithDunderBoolRaisingPropagatesException) { 55 HandleScope scope(thread_); 56 ASSERT_FALSE(runFromCStr(runtime_, R"( 57class Foo: 58 def __bool__(self): 59 raise UserWarning('') 60value = Foo() 61)") 62 .isError()); 63 Object value(&scope, mainModuleAt(runtime_, "value")); 64 Object result(&scope, Interpreter::isTrue(thread_, *value)); 65 EXPECT_TRUE(raised(*result, LayoutId::kUserWarning)); 66} 67 68TEST_F(InterpreterTest, IsTrueWithDunderLenRaisingPropagatesException) { 69 HandleScope scope(thread_); 70 ASSERT_FALSE(runFromCStr(runtime_, R"( 71class Foo: 72 def __len__(self): 73 raise UserWarning('') 74value = Foo() 75)") 76 .isError()); 77 Object value(&scope, mainModuleAt(runtime_, "value")); 78 Object result(&scope, Interpreter::isTrue(thread_, *value)); 79 EXPECT_TRUE(raised(*result, LayoutId::kUserWarning)); 80} 81 82TEST_F(InterpreterTest, IsTrueWithIntSubclassDunderLenUsesBaseInt) { 83 HandleScope scope(thread_); 84 ASSERT_FALSE(runFromCStr(runtime_, R"( 85class Foo(int): pass 86class Bar: 87 def __init__(self, length): 88 self.length = Foo(length) 89 def __len__(self): 90 return self.length 91true_value = Bar(10) 92false_value = Bar(0) 93)") 94 .isError()); 95 Object true_value(&scope, mainModuleAt(runtime_, "true_value")); 96 Object false_value(&scope, mainModuleAt(runtime_, "false_value")); 97 EXPECT_EQ(Interpreter::isTrue(thread_, *true_value), Bool::trueObj()); 98 EXPECT_EQ(Interpreter::isTrue(thread_, *false_value), Bool::falseObj()); 99} 100 101TEST_F(InterpreterTest, IsTrueDunderLen) { 102 HandleScope scope(thread_); 103 104 List nonempty_list(&scope, runtime_->newList()); 105 Object elt(&scope, NoneType::object()); 106 runtime_->listAdd(thread_, nonempty_list, elt); 107 108 EXPECT_EQ(Interpreter::isTrue(thread_, *nonempty_list), Bool::trueObj()); 109 110 List empty_list(&scope, runtime_->newList()); 111 EXPECT_EQ(Interpreter::isTrue(thread_, *empty_list), Bool::falseObj()); 112} 113 114TEST_F(InterpreterTest, UnaryOperationWithIntReturnsInt) { 115 HandleScope scope(thread_); 116 Object value(&scope, runtime_->newInt(23)); 117 Object result(&scope, 118 Interpreter::unaryOperation(thread_, value, ID(__pos__))); 119 EXPECT_TRUE(isIntEqualsWord(*result, 23)); 120} 121 122TEST_F(InterpreterTest, UnaryOperationWithBadTypeRaisesTypeError) { 123 HandleScope scope(thread_); 124 Object value(&scope, NoneType::object()); 125 Object result(&scope, 126 Interpreter::unaryOperation(thread_, value, ID(__invert__))); 127 EXPECT_TRUE( 128 raisedWithStr(*result, LayoutId::kTypeError, 129 "bad operand type for unary '__invert__': 'NoneType'")); 130} 131 132TEST_F(InterpreterTest, UnaryOperationWithCustomDunderInvertReturnsString) { 133 HandleScope scope(thread_); 134 ASSERT_FALSE(runFromCStr(runtime_, R"( 135class C: 136 def __invert__(self): 137 return "custom invert" 138c = C() 139)") 140 .isError()); 141 Object c(&scope, mainModuleAt(runtime_, "c")); 142 Object result(&scope, 143 Interpreter::unaryOperation(thread_, c, ID(__invert__))); 144 EXPECT_TRUE(isStrEqualsCStr(*result, "custom invert")); 145} 146 147TEST_F(InterpreterTest, UnaryOperationWithCustomRaisingDunderNegPropagates) { 148 HandleScope scope(thread_); 149 ASSERT_FALSE(runFromCStr(runtime_, R"( 150class C: 151 def __neg__(self): 152 raise UserWarning('') 153c = C() 154)") 155 .isError()); 156 Object c(&scope, mainModuleAt(runtime_, "c")); 157 Object result(&scope, Interpreter::unaryOperation(thread_, c, ID(__neg__))); 158 EXPECT_TRUE(raised(*result, LayoutId::kUserWarning)); 159} 160 161TEST_F(InterpreterTest, UnaryNotWithRaisingDunderBool) { 162 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 163class C: 164 def __bool__(self): 165 raise RuntimeError("too cool for bool") 166 167not C() 168)"), 169 LayoutId::kRuntimeError, "too cool for bool")); 170} 171 172TEST_F(InterpreterTest, BinaryOpCachedInsertsDependencyForBothOperandsTypes) { 173 HandleScope scope(thread_); 174 EXPECT_FALSE(runFromCStr(runtime_, R"( 175class A: 176 def __add__(self, other): 177 return "from class A" 178 179class B: 180 pass 181 182def cache_binary_op(a, b): 183 return a + b 184 185a = A() 186b = B() 187A__add__ = A.__add__ 188result = cache_binary_op(a, b) 189)") 190 .isError()); 191 ASSERT_TRUE( 192 isStrEqualsCStr(mainModuleAt(runtime_, "result"), "from class A")); 193 194 Function cache_binary_op(&scope, mainModuleAt(runtime_, "cache_binary_op")); 195 MutableTuple caches(&scope, cache_binary_op.caches()); 196 Object a(&scope, mainModuleAt(runtime_, "a")); 197 Object b(&scope, mainModuleAt(runtime_, "b")); 198 Type type_a(&scope, mainModuleAt(runtime_, "A")); 199 Type type_b(&scope, mainModuleAt(runtime_, "B")); 200 BinaryOpFlags flag; 201 ASSERT_EQ(icLookupBinaryOp(*caches, 0, a.layoutId(), b.layoutId(), &flag), 202 mainModuleAt(runtime_, "A__add__")); 203 204 // Verify that A.__add__ has the dependent. 205 Object left_op_name(&scope, runtime_->symbols()->at(ID(__add__))); 206 Object type_a_attr(&scope, typeValueCellAt(*type_a, *left_op_name)); 207 ASSERT_TRUE(type_a_attr.isValueCell()); 208 ASSERT_TRUE(ValueCell::cast(*type_a_attr).dependencyLink().isWeakLink()); 209 EXPECT_EQ( 210 WeakLink::cast(ValueCell::cast(*type_a_attr).dependencyLink()).referent(), 211 *cache_binary_op); 212 213 // Verify that B.__radd__ has the dependent. 214 Object right_op_name(&scope, runtime_->symbols()->at(ID(__radd__))); 215 Object type_b_attr(&scope, typeValueCellAt(*type_b, *right_op_name)); 216 ASSERT_TRUE(type_b_attr.isValueCell()); 217 ASSERT_TRUE(ValueCell::cast(*type_b_attr).dependencyLink().isWeakLink()); 218 EXPECT_EQ( 219 WeakLink::cast(ValueCell::cast(*type_b_attr).dependencyLink()).referent(), 220 *cache_binary_op); 221} 222 223TEST_F(InterpreterTest, BinaryOpInvokesSelfMethod) { 224 HandleScope scope(thread_); 225 226 ASSERT_FALSE(runFromCStr(runtime_, R"( 227class C: 228 def __sub__(self, other): 229 return (C, '__sub__', self, other) 230 231left = C() 232right = C() 233)") 234 .isError()); 235 236 Object left(&scope, mainModuleAt(runtime_, "left")); 237 Object right(&scope, mainModuleAt(runtime_, "right")); 238 Object c_class(&scope, mainModuleAt(runtime_, "C")); 239 240 Object result_obj( 241 &scope, Interpreter::binaryOperation(thread_, Interpreter::BinaryOp::SUB, 242 left, right)); 243 ASSERT_TRUE(result_obj.isTuple()); 244 Tuple result(&scope, *result_obj); 245 ASSERT_EQ(result.length(), 4); 246 EXPECT_EQ(result.at(0), *c_class); 247 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "__sub__")); 248 EXPECT_EQ(result.at(2), *left); 249 EXPECT_EQ(result.at(3), *right); 250} 251 252TEST_F(InterpreterTest, BinaryOpInvokesSelfMethodIgnoresReflectedMethod) { 253 HandleScope scope(thread_); 254 255 ASSERT_FALSE(runFromCStr(runtime_, R"( 256class C: 257 def __sub__(self, other): 258 return (C, '__sub__', self, other) 259 def __rsub__(self, other): 260 return (C, '__rsub__', self, other) 261 262left = C() 263right = C() 264)") 265 .isError()); 266 267 Object left(&scope, mainModuleAt(runtime_, "left")); 268 Object right(&scope, mainModuleAt(runtime_, "right")); 269 Object c_class(&scope, mainModuleAt(runtime_, "C")); 270 271 Object result_obj( 272 &scope, Interpreter::binaryOperation(thread_, Interpreter::BinaryOp::SUB, 273 left, right)); 274 ASSERT_TRUE(result_obj.isTuple()); 275 Tuple result(&scope, *result_obj); 276 ASSERT_EQ(result.length(), 4); 277 EXPECT_EQ(result.at(0), *c_class); 278 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "__sub__")); 279 EXPECT_EQ(result.at(2), *left); 280 EXPECT_EQ(result.at(3), *right); 281} 282 283TEST_F(InterpreterTest, BinaryOperationInvokesSubclassReflectedMethod) { 284 HandleScope scope(thread_); 285 286 ASSERT_FALSE(runFromCStr(runtime_, R"( 287class C: 288 def __sub__(self, other): 289 return (C, '__sub__', self, other) 290 291class D(C): 292 def __rsub__(self, other): 293 return (D, '__rsub__', self, other) 294 295left = C() 296right = D() 297)") 298 .isError()); 299 300 Object left(&scope, mainModuleAt(runtime_, "left")); 301 Object right(&scope, mainModuleAt(runtime_, "right")); 302 Object d_class(&scope, mainModuleAt(runtime_, "D")); 303 304 Object result_obj( 305 &scope, Interpreter::binaryOperation(thread_, Interpreter::BinaryOp::SUB, 306 left, right)); 307 ASSERT_TRUE(result_obj.isTuple()); 308 Tuple result(&scope, *result_obj); 309 ASSERT_EQ(result.length(), 4); 310 EXPECT_EQ(result.at(0), *d_class); 311 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "__rsub__")); 312 EXPECT_EQ(result.at(2), *right); 313 EXPECT_EQ(result.at(3), *left); 314} 315 316TEST_F(InterpreterTest, BinaryOperationInvokesOtherReflectedMethod) { 317 HandleScope scope(thread_); 318 319 ASSERT_FALSE(runFromCStr(runtime_, R"( 320class C: 321 pass 322 323class D: 324 def __rsub__(self, other): 325 return (D, '__rsub__', self, other) 326 327left = C() 328right = D() 329)") 330 .isError()); 331 332 Object left(&scope, mainModuleAt(runtime_, "left")); 333 Object right(&scope, mainModuleAt(runtime_, "right")); 334 Object d_class(&scope, mainModuleAt(runtime_, "D")); 335 336 Object result_obj( 337 &scope, Interpreter::binaryOperation(thread_, Interpreter::BinaryOp::SUB, 338 left, right)); 339 ASSERT_TRUE(result_obj.isTuple()); 340 Tuple result(&scope, *result_obj); 341 ASSERT_EQ(result.length(), 4); 342 EXPECT_EQ(result.at(0), *d_class); 343 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "__rsub__")); 344 EXPECT_EQ(result.at(2), *right); 345 EXPECT_EQ(result.at(3), *left); 346} 347 348TEST_F( 349 InterpreterTest, 350 BinaryOperationInvokesLeftMethodWhenReflectedMethodReturnsNotImplemented) { 351 ASSERT_FALSE(runFromCStr(runtime_, R"( 352trace = "" 353class C: 354 def __add__(self, other): 355 global trace 356 trace += "C.__add__," 357 return "C.__add__" 358 359 def __radd__(self, other): 360 raise Exception("should not be called") 361 362 363class D(C): 364 def __add__(self, other): 365 raise Exception("should not be called") 366 367 def __radd__(self, other): 368 global trace 369 trace += "D.__radd__," 370 return NotImplemented 371 372result = C() + D() 373)") 374 .isError()); 375 376 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "C.__add__")); 377 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "trace"), 378 "D.__radd__,C.__add__,")); 379} 380 381TEST_F(InterpreterTest, BinaryOperationLookupPropagatesException) { 382 HandleScope scope(thread_); 383 ASSERT_FALSE(runFromCStr(runtime_, R"( 384class RaisingDescriptor: 385 def __get__(self, obj, type): 386 raise UserWarning() 387class A: 388 __mul__ = RaisingDescriptor() 389a = A() 390)") 391 .isError()); 392 Object a(&scope, mainModuleAt(runtime_, "a")); 393 Object result(&scope, Interpreter::binaryOperation( 394 thread_, Interpreter::BinaryOp::MUL, a, a)); 395 EXPECT_TRUE(raised(*result, LayoutId::kUserWarning)); 396} 397 398TEST_F(InterpreterTest, 399 BinaryOperationLookupReflectedMethodPropagatesException) { 400 HandleScope scope(thread_); 401 ASSERT_FALSE(runFromCStr(runtime_, R"( 402class RaisingDescriptor: 403 def __get__(self, obj, type): 404 raise UserWarning() 405class A: 406 def __mul__(self, other): 407 return 42 408class B(A): 409 __rmul__ = RaisingDescriptor() 410a = A() 411b = B() 412)") 413 .isError()); 414 Object a(&scope, mainModuleAt(runtime_, "a")); 415 Object b(&scope, mainModuleAt(runtime_, "b")); 416 Object result(&scope, Interpreter::binaryOperation( 417 thread_, Interpreter::BinaryOp::MUL, a, b)); 418 EXPECT_TRUE(raised(*result, LayoutId::kUserWarning)); 419} 420 421TEST_F(InterpreterTest, BinaryOperationSetMethodSetsMethod) { 422 HandleScope scope(thread_); 423 Object v0(&scope, runtime_->newInt(13)); 424 Object v1(&scope, runtime_->newInt(42)); 425 Object method(&scope, NoneType::object()); 426 BinaryOpFlags flags; 427 EXPECT_TRUE(isIntEqualsWord( 428 Interpreter::binaryOperationSetMethod(thread_, Interpreter::BinaryOp::SUB, 429 v0, v1, &method, &flags), 430 -29)); 431 EXPECT_TRUE(method.isFunction()); 432 EXPECT_EQ(flags, kBinaryOpNotImplementedRetry); 433 434 Object v2(&scope, runtime_->newInt(3)); 435 Object v3(&scope, runtime_->newInt(8)); 436 ASSERT_EQ(v0.layoutId(), v2.layoutId()); 437 ASSERT_EQ(v1.layoutId(), v3.layoutId()); 438 EXPECT_TRUE(isIntEqualsWord( 439 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *v2, *v3), 440 -5)); 441} 442 443TEST_F(InterpreterTest, 444 BinaryOperationSetMethodSetsReflectedMethodNotImplementedRetry) { 445 HandleScope scope(thread_); 446 ASSERT_FALSE(runFromCStr(runtime_, R"( 447class A: 448 def __init__(self, x): 449 self.x = x 450 def __sub__(self, other): 451 raise UserWarning("should not be called") 452class ASub(A): 453 def __rsub__(self, other): 454 return (self, other) 455v0 = A(3) 456v1 = ASub(7) 457v2 = A(8) 458v3 = ASub(2) 459)") 460 .isError()); 461 Object v0(&scope, mainModuleAt(runtime_, "v0")); 462 Object v1(&scope, mainModuleAt(runtime_, "v1")); 463 Object v2(&scope, mainModuleAt(runtime_, "v2")); 464 Object v3(&scope, mainModuleAt(runtime_, "v3")); 465 466 Object method(&scope, NoneType::object()); 467 BinaryOpFlags flags; 468 Object result_obj(&scope, Interpreter::binaryOperationSetMethod( 469 thread_, Interpreter::BinaryOp::SUB, v0, v1, 470 &method, &flags)); 471 ASSERT_TRUE(result_obj.isTuple()); 472 Tuple result(&scope, *result_obj); 473 ASSERT_EQ(result.length(), 2); 474 EXPECT_EQ(result.at(0), v1); 475 EXPECT_EQ(result.at(1), v0); 476 EXPECT_TRUE(method.isFunction()); 477 EXPECT_EQ(flags, kBinaryOpReflected | kBinaryOpNotImplementedRetry); 478 479 ASSERT_EQ(v0.layoutId(), v2.layoutId()); 480 ASSERT_EQ(v1.layoutId(), v3.layoutId()); 481 result_obj = 482 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *v2, *v3); 483 ASSERT_TRUE(result.isTuple()); 484 result = *result_obj; 485 ASSERT_EQ(result.length(), 2); 486 EXPECT_EQ(result.at(0), v3); 487 EXPECT_EQ(result.at(1), v2); 488} 489 490TEST_F(InterpreterTest, BinaryOperationSetMethodSetsReflectedMethod) { 491 HandleScope scope(thread_); 492 ASSERT_FALSE(runFromCStr(runtime_, R"( 493class A: 494 def __init__(self, x): 495 self.x = x 496class B: 497 def __init__(self, x): 498 self.x = x 499 def __rsub__(self, other): 500 return other.x - self.x 501v0 = A(-4) 502v1 = B(8) 503v2 = A(33) 504v3 = B(-12) 505)") 506 .isError()); 507 Object v0(&scope, mainModuleAt(runtime_, "v0")); 508 Object v1(&scope, mainModuleAt(runtime_, "v1")); 509 Object v2(&scope, mainModuleAt(runtime_, "v2")); 510 Object v3(&scope, mainModuleAt(runtime_, "v3")); 511 512 Object method(&scope, NoneType::object()); 513 BinaryOpFlags flags; 514 EXPECT_TRUE(isIntEqualsWord( 515 Interpreter::binaryOperationSetMethod(thread_, Interpreter::BinaryOp::SUB, 516 v0, v1, &method, &flags), 517 -12)); 518 EXPECT_TRUE(method.isFunction()); 519 EXPECT_EQ(flags, kBinaryOpReflected); 520 521 ASSERT_EQ(v0.layoutId(), v2.layoutId()); 522 ASSERT_EQ(v1.layoutId(), v3.layoutId()); 523 EXPECT_TRUE(isIntEqualsWord( 524 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *v2, *v3), 525 45)); 526} 527 528TEST_F(InterpreterTest, BinaryOperationSetMethodSetsMethodNotImplementedRetry) { 529 HandleScope scope(thread_); 530 ASSERT_FALSE(runFromCStr(runtime_, R"( 531class A: 532 def __init__(self, x): 533 self.x = x 534 def __sub__(self, other): 535 return other.x - self.x 536class B: 537 def __init__(self, x): 538 self.x = x 539 def __rsub__(self, other): 540 return self.x - other.x 541v0 = A(4) 542v1 = B(6) 543v2 = A(9) 544v3 = B(1) 545)") 546 .isError()); 547 Object v0(&scope, mainModuleAt(runtime_, "v0")); 548 Object v1(&scope, mainModuleAt(runtime_, "v1")); 549 Object v2(&scope, mainModuleAt(runtime_, "v2")); 550 Object v3(&scope, mainModuleAt(runtime_, "v3")); 551 552 Object method(&scope, NoneType::object()); 553 BinaryOpFlags flags; 554 EXPECT_TRUE(isIntEqualsWord( 555 Interpreter::binaryOperationSetMethod(thread_, Interpreter::BinaryOp::SUB, 556 v0, v1, &method, &flags), 557 2)); 558 EXPECT_TRUE(method.isFunction()); 559 EXPECT_EQ(flags, kBinaryOpNotImplementedRetry); 560 561 ASSERT_EQ(v0.layoutId(), v2.layoutId()); 562 ASSERT_EQ(v1.layoutId(), v3.layoutId()); 563 EXPECT_TRUE(isIntEqualsWord( 564 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *v2, *v3), 565 -8)); 566} 567 568TEST_F(InterpreterTest, DoBinaryOpWithCacheHitCallsCachedMethod) { 569 HandleScope scope(thread_); 570 571 word left = SmallInt::kMaxValue + 1; 572 word right = -13; 573 const byte bytecode[] = { 574 LOAD_CONST, 0, LOAD_CONST, 1, BINARY_SUBTRACT, 0, RETURN_VALUE, 0, 575 }; 576 Object left_obj(&scope, runtime_->newInt(left)); 577 Object right_obj(&scope, runtime_->newInt(right)); 578 Tuple consts(&scope, runtime_->newTupleWith2(left_obj, right_obj)); 579 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 580 581 Object qualname(&scope, Str::empty()); 582 Module module(&scope, findMainModule(runtime_)); 583 Function function( 584 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 585 586 // Update inline cache. 587 EXPECT_TRUE( 588 isIntEqualsWord(Interpreter::call0(thread_, function), left - right)); 589 590 ASSERT_TRUE(function.caches().isTuple()); 591 MutableTuple caches(&scope, function.caches()); 592 BinaryOpFlags dummy; 593 ASSERT_FALSE(icLookupBinaryOp(*caches, 0, LayoutId::kLargeInt, 594 LayoutId::kSmallInt, &dummy) 595 .isErrorNotFound()); 596 597 // Call from inline cache. 598 EXPECT_TRUE( 599 isIntEqualsWord(Interpreter::call0(thread_, function), left - right)); 600} 601 602TEST_F(InterpreterTest, DoBinaryOpWithCacheHitCallsRetry) { 603 HandleScope scope(thread_); 604 ASSERT_FALSE(runFromCStr(runtime_, R"( 605class MyInt(int): 606 def __sub__(self, other): 607 return NotImplemented 608 def __rsub__(self, other): 609 return NotImplemented 610v0 = MyInt(3) 611v1 = 7 612)") 613 .isError()); 614 Object v0(&scope, mainModuleAt(runtime_, "v0")); 615 Object v1(&scope, mainModuleAt(runtime_, "v1")); 616 617 Tuple consts(&scope, runtime_->newTupleWith2(v0, v1)); 618 const byte bytecode[] = { 619 LOAD_CONST, 0, LOAD_CONST, 1, BINARY_SUBTRACT, 0, RETURN_VALUE, 0, 620 }; 621 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 622 623 Object qualname(&scope, Str::empty()); 624 Module module(&scope, findMainModule(runtime_)); 625 Function function( 626 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 627 628 // Update inline cache. 629 EXPECT_TRUE(isIntEqualsWord(Interpreter::call0(thread_, function), -4)); 630 631 ASSERT_TRUE(function.caches().isTuple()); 632 MutableTuple caches(&scope, function.caches()); 633 BinaryOpFlags dummy; 634 ASSERT_FALSE( 635 icLookupBinaryOp(*caches, 0, v0.layoutId(), v1.layoutId(), &dummy) 636 .isErrorNotFound()); 637 638 // Should hit the cache for __sub__ and then call binaryOperationRetry(). 639 EXPECT_TRUE(isIntEqualsWord(Interpreter::call0(thread_, function), -4)); 640} 641 642TEST_F(InterpreterTest, DoBinaryOpWithSmallIntsRewritesOpcode) { 643 HandleScope scope(thread_); 644 645 word left = 7; 646 word right = -13; 647 Object left_obj(&scope, runtime_->newInt(left)); 648 Object right_obj(&scope, runtime_->newInt(right)); 649 Tuple consts(&scope, runtime_->newTupleWith2(left_obj, right_obj)); 650 const byte bytecode[] = { 651 LOAD_CONST, 0, LOAD_CONST, 1, BINARY_SUBTRACT, 0, RETURN_VALUE, 0, 652 }; 653 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 654 655 Object qualname(&scope, Str::empty()); 656 Module module(&scope, findMainModule(runtime_)); 657 Function function( 658 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 659 660 // Update the opcode. 661 ASSERT_TRUE( 662 isIntEqualsWord(Interpreter::call0(thread_, function), left - right)); 663 664 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 665 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), BINARY_SUB_SMALLINT); 666 667 // Updated opcode returns the same value. 668 EXPECT_TRUE( 669 isIntEqualsWord(Interpreter::call0(thread_, function), left - right)); 670} 671 672static bool functionMatchesRef1(const Function& function, 673 const Object& reference, const Object& arg0) { 674 Thread* thread = Thread::current(); 675 HandleScope scope(thread); 676 Object expected(&scope, Interpreter::call1(thread, reference, arg0)); 677 EXPECT_FALSE(expected.isError()); 678 Object actual(&scope, Interpreter::call1(thread, function, arg0)); 679 EXPECT_FALSE(actual.isError()); 680 return Runtime::objectEquals(thread, *expected, *actual) == Bool::trueObj(); 681} 682 683static bool functionMatchesRef2(const Function& function, 684 const Object& reference, const Object& arg0, 685 const Object& arg1) { 686 Thread* thread = Thread::current(); 687 HandleScope scope(thread); 688 Object expected(&scope, Interpreter::call2(thread, reference, arg0, arg1)); 689 EXPECT_FALSE(expected.isError()); 690 Object actual(&scope, Interpreter::call2(thread, function, arg0, arg1)); 691 EXPECT_FALSE(actual.isError()); 692 return Runtime::objectEquals(thread, *expected, *actual) == Bool::trueObj(); 693} 694 695// Test that `function(arg0, arg1) == reference(arg0, arg1)` with the assumption 696// that `function` contains a `BINARY_OP_MONOMORPHIC` opcode that will be 697// specialized to `opcode_specialized` when called with `arg0` and `arg1`. 698// Calling the function with `arg_o` should trigger a revert to 699// `BINARY_OP_MONOMORPHIC`. 700static void testBinaryOpRewrite(const Function& function, 701 const Function& reference, 702 Bytecode opcode_specialized, const Object& arg0, 703 const Object& arg1, const Object& arg_o) { 704 EXPECT_TRUE(containsBytecode(function, BINARY_OP_ANAMORPHIC)); 705 706 EXPECT_TRUE(functionMatchesRef2(function, reference, arg0, arg1)); 707 EXPECT_FALSE(containsBytecode(function, BINARY_OP_ANAMORPHIC)); 708 EXPECT_TRUE(containsBytecode(function, opcode_specialized)); 709 EXPECT_TRUE(functionMatchesRef2(function, reference, arg1, arg0)); 710 EXPECT_TRUE(containsBytecode(function, opcode_specialized)); 711 712 EXPECT_TRUE(functionMatchesRef2(function, reference, arg0, arg_o)); 713 EXPECT_TRUE(containsBytecode(function, BINARY_OP_MONOMORPHIC)); 714 EXPECT_FALSE(containsBytecode(function, opcode_specialized)); 715 716 EXPECT_TRUE(functionMatchesRef2(function, reference, arg0, arg1)); 717} 718 719TEST_F(InterpreterTest, CallFunctionAnamorphicRewritesToCallFunctionTypeNew) { 720 HandleScope scope(thread_); 721 ASSERT_FALSE(runFromCStr(runtime_, R"( 722class C: 723 def __new__(cls): 724 return object.__new__(cls) 725def foo(fn): 726 return fn() 727def non_type(): 728 return 5 729)") 730 .isError()); 731 Function function(&scope, mainModuleAt(runtime_, "foo")); 732 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_ANAMORPHIC)); 733 734 Type type(&scope, mainModuleAt(runtime_, "C")); 735 Object expected(&scope, Interpreter::call1(thread_, function, type)); 736 EXPECT_FALSE(expected.isError()); 737 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_TYPE_NEW)); 738 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 739 740 Object non_type(&scope, mainModuleAt(runtime_, "non_type")); 741 expected = Interpreter::call1(thread_, function, non_type); 742 EXPECT_FALSE(expected.isError()); 743 EXPECT_TRUE(isIntEqualsWord(*expected, 5)); 744 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 745} 746 747TEST_F(InterpreterTest, 748 CallFunctionTypeNewWithNewDunderNewRewritesToCallFunction) { 749 HandleScope scope(thread_); 750 ASSERT_FALSE(runFromCStr(runtime_, R"( 751class C: 752 def __new__(cls): 753 return object.__new__(cls) 754def foo(fn): 755 return fn() 756def new_new(cls): 757 return 5 758)") 759 .isError()); 760 Function function(&scope, mainModuleAt(runtime_, "foo")); 761 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_ANAMORPHIC)); 762 763 Type type(&scope, mainModuleAt(runtime_, "C")); 764 Object expected(&scope, Interpreter::call1(thread_, function, type)); 765 EXPECT_FALSE(expected.isError()); 766 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_TYPE_NEW)); 767 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 768 769 // Invalidate cache 770 Object new_new(&scope, mainModuleAt(runtime_, "new_new")); 771 typeAtPutById(thread_, type, ID(__new__), new_new); 772 773 // Cache miss 774 expected = Interpreter::call1(thread_, function, type); 775 EXPECT_FALSE(expected.isError()); 776 EXPECT_TRUE(isIntEqualsWord(*expected, 5)); 777 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 778} 779 780TEST_F(InterpreterTest, 781 CallFunctionTypeNewWithNewDunderInitRewritesToCallFunction) { 782 HandleScope scope(thread_); 783 ASSERT_FALSE(runFromCStr(runtime_, R"( 784class C: 785 def __new__(cls): 786 return object.__new__(cls) 787 def __init__(self): 788 pass 789def foo(fn): 790 return fn() 791def new_init(self): 792 pass 793)") 794 .isError()); 795 Function function(&scope, mainModuleAt(runtime_, "foo")); 796 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_ANAMORPHIC)); 797 798 Type type(&scope, mainModuleAt(runtime_, "C")); 799 Object expected(&scope, Interpreter::call1(thread_, function, type)); 800 EXPECT_FALSE(expected.isError()); 801 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_TYPE_NEW)); 802 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 803 804 // Invalidate cache 805 Object new_init(&scope, mainModuleAt(runtime_, "new_init")); 806 typeAtPutById(thread_, type, ID(__init__), new_init); 807 808 // Cache miss 809 expected = Interpreter::call1(thread_, function, type); 810 EXPECT_FALSE(expected.isError()); 811 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 812 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 813} 814 815TEST_F(InterpreterTest, CallFunctionAnamorphicRewritesToCallFunctionTypeInit) { 816 HandleScope scope(thread_); 817 ASSERT_FALSE(runFromCStr(runtime_, R"( 818class C: 819 def __init__(self): 820 pass 821def foo(fn): 822 return fn() 823def non_type(): 824 return 5 825)") 826 .isError()); 827 Function function(&scope, mainModuleAt(runtime_, "foo")); 828 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_ANAMORPHIC)); 829 830 Type type(&scope, mainModuleAt(runtime_, "C")); 831 Object expected(&scope, Interpreter::call1(thread_, function, type)); 832 EXPECT_FALSE(expected.isError()); 833 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_TYPE_INIT)); 834 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 835 836 Object non_type(&scope, mainModuleAt(runtime_, "non_type")); 837 expected = Interpreter::call1(thread_, function, non_type); 838 EXPECT_FALSE(expected.isError()); 839 EXPECT_TRUE(isIntEqualsWord(*expected, 5)); 840 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 841} 842 843TEST_F(InterpreterTest, 844 CallFunctionTypeInitWithNewDunderInitRewritesToCallFunction) { 845 HandleScope scope(thread_); 846 ASSERT_FALSE(runFromCStr(runtime_, R"( 847class C: 848 def __init__(self): 849 pass 850def foo(fn): 851 return fn() 852def new_init(self): 853 pass 854)") 855 .isError()); 856 Function function(&scope, mainModuleAt(runtime_, "foo")); 857 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_ANAMORPHIC)); 858 859 Type type(&scope, mainModuleAt(runtime_, "C")); 860 Object expected(&scope, Interpreter::call1(thread_, function, type)); 861 EXPECT_FALSE(expected.isError()); 862 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_TYPE_INIT)); 863 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 864 865 // Invalidate cache 866 Object new_init(&scope, mainModuleAt(runtime_, "new_init")); 867 typeAtPutById(thread_, type, ID(__init__), new_init); 868 869 // Cache miss 870 expected = Interpreter::call1(thread_, function, type); 871 EXPECT_FALSE(expected.isError()); 872 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 873 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 874} 875 876TEST_F(InterpreterTest, 877 CallFunctionTypeInitWithNewDunderNewRewritesToCallFunction) { 878 HandleScope scope(thread_); 879 ASSERT_FALSE(runFromCStr(runtime_, R"( 880class C: 881 def __init__(self): 882 pass 883def foo(fn): 884 return fn() 885def new_new(self): 886 pass 887)") 888 .isError()); 889 Function function(&scope, mainModuleAt(runtime_, "foo")); 890 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_ANAMORPHIC)); 891 892 Type type(&scope, mainModuleAt(runtime_, "C")); 893 Object expected(&scope, Interpreter::call1(thread_, function, type)); 894 EXPECT_FALSE(expected.isError()); 895 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION_TYPE_INIT)); 896 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 897 898 // Invalidate cache 899 Object new_new(&scope, mainModuleAt(runtime_, "new_new")); 900 typeAtPutById(thread_, type, ID(__new__), new_new); 901 902 // Cache miss 903 expected = Interpreter::call1(thread_, function, type); 904 EXPECT_FALSE(expected.isError()); 905 EXPECT_EQ(expected.layoutId(), type.instanceLayoutId()); 906 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 907} 908 909// Test that `function(arg0) == reference(arg0)` with the assumption 910// that `function` contains the original unary opcode that will be 911// specialized to `opcode_specialized` when called with `arg0`. 912// Calling the function with `arg_o` should trigger a revert to 913// the unspecialized unary op. 914static void testUnaryOpRewrite(const Function& function, 915 const Function& reference, 916 Bytecode opcode_unspecialized, 917 Bytecode opcode_specialized, const Object& arg0, 918 const Object& arg_o) { 919 EXPECT_TRUE(containsBytecode(function, UNARY_OP_ANAMORPHIC)); 920 921 EXPECT_TRUE(functionMatchesRef1(function, reference, arg0)); 922 EXPECT_FALSE(containsBytecode(function, BINARY_OP_ANAMORPHIC)); 923 EXPECT_TRUE(containsBytecode(function, opcode_specialized)); 924 EXPECT_TRUE(functionMatchesRef1(function, reference, arg0)); 925 EXPECT_TRUE(containsBytecode(function, opcode_specialized)); 926 927 EXPECT_TRUE(functionMatchesRef1(function, reference, arg_o)); 928 EXPECT_TRUE(containsBytecode(function, opcode_unspecialized)); 929 EXPECT_FALSE(containsBytecode(function, opcode_specialized)); 930 931 EXPECT_TRUE(functionMatchesRef1(function, reference, arg0)); 932} 933 934TEST_F(InterpreterTest, UnaryOpAnamorphicRewritesToUnaryNegativeSmallInt) { 935 HandleScope scope(thread_); 936 ASSERT_FALSE(runFromCStr(runtime_, R"( 937def function(obj): 938 return -obj 939reference = int.__neg__ 940)") 941 .isError()); 942 Function function(&scope, mainModuleAt(runtime_, "function")); 943 Function reference(&scope, mainModuleAt(runtime_, "reference")); 944 Object arg0(&scope, SmallInt::fromWord(34)); 945 const uword digits2[] = {0x12345678, 0xabcdef}; 946 Object arg_l(&scope, runtime_->newLargeIntWithDigits(digits2)); 947 testUnaryOpRewrite(function, reference, UNARY_NEGATIVE, 948 UNARY_NEGATIVE_SMALLINT, arg0, arg_l); 949} 950 951TEST_F(InterpreterTest, BinaryOpAnamorphicRewritesToBinaryAddSmallInt) { 952 HandleScope scope(thread_); 953 ASSERT_FALSE(runFromCStr(runtime_, R"( 954def function(a, b): 955 return a + b 956reference = int.__add__ 957)") 958 .isError()); 959 Function function(&scope, mainModuleAt(runtime_, "function")); 960 Function reference(&scope, mainModuleAt(runtime_, "reference")); 961 Object arg0(&scope, SmallInt::fromWord(34)); 962 Object arg1(&scope, SmallInt::fromWord(12)); 963 const uword digits2[] = {0x12345678, 0xabcdef}; 964 Object arg_l(&scope, runtime_->newLargeIntWithDigits(digits2)); 965 testBinaryOpRewrite(function, reference, BINARY_ADD_SMALLINT, arg0, arg1, 966 arg_l); 967} 968 969TEST_F(InterpreterTest, BinaryOpAnamorphicRewritesToBinaryMulSmallInt) { 970 HandleScope scope(thread_); 971 ASSERT_FALSE(runFromCStr(runtime_, R"( 972def function(a, b): 973 return a * b 974reference = int.__mul__ 975)") 976 .isError()); 977 Function function(&scope, mainModuleAt(runtime_, "function")); 978 Function reference(&scope, mainModuleAt(runtime_, "reference")); 979 Object arg0(&scope, SmallInt::fromWord(34)); 980 Object arg1(&scope, SmallInt::fromWord(12)); 981 const uword digits2[] = {0x12345678, 0xabcdef}; 982 Object arg_l(&scope, runtime_->newLargeIntWithDigits(digits2)); 983 testBinaryOpRewrite(function, reference, BINARY_MUL_SMALLINT, arg0, arg1, 984 arg_l); 985} 986 987TEST_F(InterpreterTest, BinaryOpAnamorphicRewritesToBinarySubSmallInt) { 988 HandleScope scope(thread_); 989 ASSERT_FALSE(runFromCStr(runtime_, R"( 990def function(a, b): 991 return a - b 992reference = int.__sub__ 993)") 994 .isError()); 995 Function function(&scope, mainModuleAt(runtime_, "function")); 996 Function reference(&scope, mainModuleAt(runtime_, "reference")); 997 Object arg0(&scope, SmallInt::fromWord(94)); 998 Object arg1(&scope, SmallInt::fromWord(21)); 999 const uword digits2[] = {0x12345678, 0xabcdef}; 1000 Object arg_l(&scope, runtime_->newLargeIntWithDigits(digits2)); 1001 testBinaryOpRewrite(function, reference, BINARY_SUB_SMALLINT, arg0, arg1, 1002 arg_l); 1003} 1004 1005TEST_F(InterpreterTest, BinaryOpAnamorphicRewritesToBinaryOrSmallInt) { 1006 HandleScope scope(thread_); 1007 ASSERT_FALSE(runFromCStr(runtime_, R"( 1008def function(a, b): 1009 return a | b 1010reference = int.__or__ 1011)") 1012 .isError()); 1013 Function function(&scope, mainModuleAt(runtime_, "function")); 1014 Function reference(&scope, mainModuleAt(runtime_, "reference")); 1015 Object arg0(&scope, SmallInt::fromWord(0xa5)); 1016 Object arg1(&scope, SmallInt::fromWord(0x42)); 1017 const uword digits2[] = {0x12345678, 0xabcdef}; 1018 Object arg_l(&scope, runtime_->newLargeIntWithDigits(digits2)); 1019 testBinaryOpRewrite(function, reference, BINARY_OR_SMALLINT, arg0, arg1, 1020 arg_l); 1021} 1022 1023TEST_F(InterpreterTest, BinaryOpAnamorphicRewritesToBinaryAndSmallInt) { 1024 HandleScope scope(thread_); 1025 ASSERT_FALSE(runFromCStr(runtime_, R"( 1026def function(a, b): 1027 return a & b 1028reference = int.__and__ 1029)") 1030 .isError()); 1031 Function function(&scope, mainModuleAt(runtime_, "function")); 1032 Function reference(&scope, mainModuleAt(runtime_, "reference")); 1033 Object arg0(&scope, SmallInt::fromWord(0xa5)); 1034 Object arg1(&scope, SmallInt::fromWord(0x42)); 1035 const uword digits2[] = {0x12345678, 0xabcdef}; 1036 Object arg_l(&scope, runtime_->newLargeIntWithDigits(digits2)); 1037 testBinaryOpRewrite(function, reference, BINARY_AND_SMALLINT, arg0, arg1, 1038 arg_l); 1039} 1040 1041TEST_F(InterpreterTest, BinarySubscrWithListAndSmallInt) { 1042 HandleScope scope(thread_); 1043 ASSERT_FALSE(runFromCStr(runtime_, R"( 1044def foo(l, i): 1045 return l[i] 1046 1047l = [1,2,3] 1048)") 1049 .isError()); 1050 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1051 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1052 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1053 1054 List l(&scope, mainModuleAt(runtime_, "l")); 1055 SmallInt zero(&scope, SmallInt::fromWord(0)); 1056 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, zero), 1)); 1057 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_LIST); 1058 1059 SmallInt one(&scope, SmallInt::fromWord(1)); 1060 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, one), 2)); 1061 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_LIST); 1062} 1063 1064TEST_F(InterpreterTest, 1065 BinarySubscrAnamorphicRewritesToBinarySubscrMonomorphic) { 1066 HandleScope scope(thread_); 1067 ASSERT_FALSE(runFromCStr(runtime_, R"( 1068def foo(l, i): 1069 return l[i] 1070 1071class L: 1072 def __getitem__(self, i): return i * 2 1073 1074L__getitem__ = L.__getitem__ 1075l = L() 1076)") 1077 .isError()); 1078 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1079 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1080 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1081 1082 Object l(&scope, mainModuleAt(runtime_, "l")); 1083 SmallInt key(&scope, SmallInt::fromWord(12)); 1084 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 24)); 1085 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1086 1087 SmallInt key2(&scope, SmallInt::fromWord(13)); 1088 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key2), 26)); 1089 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1090} 1091 1092TEST_F(InterpreterTest, 1093 BinarySubscrMonomorphicRewritesToBinarySubscrPolymorphic) { 1094 HandleScope scope(thread_); 1095 ASSERT_FALSE(runFromCStr(runtime_, R"( 1096def foo(l, i): 1097 return l[i] 1098 1099class A: 1100 def __getitem__(self, i): return i * 2 1101 1102class B: 1103 def __getitem__(self, i): return i * 3 1104 1105a = A() 1106b = B() 1107)") 1108 .isError()); 1109 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1110 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1111 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1112 1113 Object a(&scope, mainModuleAt(runtime_, "a")); 1114 SmallInt key_a(&scope, SmallInt::fromWord(6)); 1115 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, a, key_a), 12)); 1116 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1117 1118 Object b(&scope, mainModuleAt(runtime_, "b")); 1119 SmallInt key_b(&scope, SmallInt::fromWord(12)); 1120 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, b, key_b), 36)); 1121 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_POLYMORPHIC); 1122} 1123 1124TEST_F( 1125 InterpreterTest, 1126 BinarySubscrDictRevertsBackToBinarySubscrMonomorphicWhenNonDictObserved) { 1127 HandleScope scope(thread_); 1128 ASSERT_FALSE(runFromCStr(runtime_, R"( 1129def foo(l, i): 1130 return l[i] 1131 1132d = {1: 2} 1133s = "abc" 1134)") 1135 .isError()); 1136 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1137 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1138 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1139 1140 Dict d(&scope, mainModuleAt(runtime_, "d")); 1141 SmallInt key(&scope, SmallInt::fromWord(1)); 1142 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, d, key), 2)); 1143 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_DICT); 1144 1145 // Revert back to caching __getitem__ when a non-list is observed. 1146 Object s(&scope, mainModuleAt(runtime_, "s")); 1147 EXPECT_TRUE(isStrEqualsCStr(Interpreter::call2(thread_, foo, s, key), "b")); 1148 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1149} 1150 1151TEST_F( 1152 InterpreterTest, 1153 BinarySubscrListRevertsBackToBinarySubscrMonomorphicWhenNonListObserved) { 1154 HandleScope scope(thread_); 1155 ASSERT_FALSE(runFromCStr(runtime_, R"( 1156def foo(l, i): 1157 return l[i] 1158 1159l = [1,2,3] 1160s = "abc" 1161)") 1162 .isError()); 1163 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1164 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1165 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1166 1167 List l(&scope, mainModuleAt(runtime_, "l")); 1168 SmallInt key(&scope, SmallInt::fromWord(1)); 1169 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 2)); 1170 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_LIST); 1171 1172 // Revert back to caching __getitem__ when a non-list is observed. 1173 Object s(&scope, mainModuleAt(runtime_, "s")); 1174 EXPECT_TRUE(isStrEqualsCStr(Interpreter::call2(thread_, foo, s, key), "b")); 1175 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1176} 1177 1178TEST_F( 1179 InterpreterTest, 1180 BinarySubscrListRevertsBackToBinarySubscrMonomorphicWhenNonSmallIntKeyObserved) { 1181 HandleScope scope(thread_); 1182 ASSERT_FALSE(runFromCStr(runtime_, R"( 1183def foo(l, i): 1184 return l[i] 1185 1186l = [1,2,3] 1187large_int = 2**64 1188)") 1189 .isError()); 1190 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1191 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1192 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1193 1194 List l(&scope, mainModuleAt(runtime_, "l")); 1195 SmallInt key(&scope, SmallInt::fromWord(1)); 1196 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 2)); 1197 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_LIST); 1198 1199 // Revert back to caching __getitem__ when the key is not SmallInt. 1200 LargeInt large_int(&scope, mainModuleAt(runtime_, "large_int")); 1201 EXPECT_TRUE(Interpreter::call2(thread_, foo, l, large_int).isError()); 1202 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1203} 1204 1205TEST_F( 1206 InterpreterTest, 1207 BinarySubscrListRevertsBackToBinarySubscrMonomorphicWhenNegativeKeyObserved) { 1208 HandleScope scope(thread_); 1209 ASSERT_FALSE(runFromCStr(runtime_, R"( 1210def foo(l, i): 1211 return l[i] 1212 1213l = [1,2,3] 1214)") 1215 .isError()); 1216 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1217 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1218 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1219 1220 List l(&scope, mainModuleAt(runtime_, "l")); 1221 SmallInt key(&scope, SmallInt::fromWord(1)); 1222 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 2)); 1223 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_LIST); 1224 1225 // Revert back to caching __getitem__ when the key is negative. 1226 SmallInt negative(&scope, SmallInt::fromWord(-1)); 1227 EXPECT_TRUE( 1228 isIntEqualsWord(Interpreter::call2(thread_, foo, l, negative), 3)); 1229 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1230} 1231 1232TEST_F(InterpreterTest, StoreSubscrWithDictRewritesToStoreSubscrDict) { 1233 HandleScope scope(thread_); 1234 ASSERT_FALSE(runFromCStr(runtime_, R"( 1235def foo(d, i): 1236 d[i] = 5 1237 return d[i] 1238 1239d = {} 1240)") 1241 .isError()); 1242 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1243 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1244 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_ANAMORPHIC); 1245 1246 Dict d(&scope, mainModuleAt(runtime_, "d")); 1247 SmallInt zero(&scope, SmallInt::fromWord(0)); 1248 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, d, zero), 5)); 1249 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_DICT); 1250 1251 SmallInt one(&scope, SmallInt::fromWord(1)); 1252 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, d, one), 5)); 1253 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_DICT); 1254} 1255 1256TEST_F(InterpreterTest, 1257 StoreSubscrDictRevertsBackToStoreSubscrMonomorphicWhenNonDictObserved) { 1258 HandleScope scope(thread_); 1259 ASSERT_FALSE(runFromCStr(runtime_, R"( 1260def foo(d, i): 1261 d[i] = 5 1262 return d[i] 1263 1264d = {1: -1} 1265b = bytearray(b"0000") 1266)") 1267 .isError()); 1268 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1269 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1270 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_ANAMORPHIC); 1271 1272 Dict d(&scope, mainModuleAt(runtime_, "d")); 1273 SmallInt key(&scope, SmallInt::fromWord(1)); 1274 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, d, key), 5)); 1275 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_DICT); 1276 1277 // Revert back to caching __getitem__ when a non-dict is observed. 1278 Object b(&scope, mainModuleAt(runtime_, "b")); 1279 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, b, key), 5)); 1280 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_MONOMORPHIC); 1281} 1282 1283TEST_F(InterpreterTest, StoreSubscrWithListAndSmallInt) { 1284 HandleScope scope(thread_); 1285 ASSERT_FALSE(runFromCStr(runtime_, R"( 1286def foo(l, i): 1287 l[i] = 5 1288 return l[i] 1289 1290l = [1,2,3] 1291)") 1292 .isError()); 1293 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1294 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1295 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_ANAMORPHIC); 1296 1297 List l(&scope, mainModuleAt(runtime_, "l")); 1298 SmallInt zero(&scope, SmallInt::fromWord(0)); 1299 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, zero), 5)); 1300 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_LIST); 1301 1302 SmallInt one(&scope, SmallInt::fromWord(1)); 1303 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, one), 5)); 1304 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_LIST); 1305} 1306 1307TEST_F(InterpreterTest, 1308 StoreSubscrListRevertsBackToStoreSubscrMonomorphicWhenNonListObserved) { 1309 HandleScope scope(thread_); 1310 ASSERT_FALSE(runFromCStr(runtime_, R"( 1311def foo(l, i): 1312 l[i] = 5 1313 return l[i] 1314 1315l = [1,2,3] 1316d = {1: -1} 1317)") 1318 .isError()); 1319 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1320 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1321 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_ANAMORPHIC); 1322 1323 List l(&scope, mainModuleAt(runtime_, "l")); 1324 SmallInt key(&scope, SmallInt::fromWord(1)); 1325 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 5)); 1326 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_LIST); 1327 1328 // Revert back to caching __getitem__ when a non-list is observed. 1329 Dict d(&scope, mainModuleAt(runtime_, "d")); 1330 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, d, key), 5)); 1331 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_MONOMORPHIC); 1332} 1333 1334TEST_F( 1335 InterpreterTest, 1336 StoreSubscrListRevertsBackToStoreSubscrMonomorphicWhenNonSmallIntKeyObserved) { 1337 HandleScope scope(thread_); 1338 ASSERT_FALSE(runFromCStr(runtime_, R"( 1339def foo(l, i): 1340 l[i] = 5 1341 return l[i] 1342 1343l = [1,2,3] 1344large_int = 2**64 1345)") 1346 .isError()); 1347 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1348 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1349 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_ANAMORPHIC); 1350 1351 List l(&scope, mainModuleAt(runtime_, "l")); 1352 SmallInt key(&scope, SmallInt::fromWord(1)); 1353 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 5)); 1354 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_LIST); 1355 1356 // Revert back to caching __getitem__ when the key is not SmallInt. 1357 LargeInt large_int(&scope, mainModuleAt(runtime_, "large_int")); 1358 EXPECT_TRUE(Interpreter::call2(thread_, foo, l, large_int).isError()); 1359 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_MONOMORPHIC); 1360} 1361 1362TEST_F( 1363 InterpreterTest, 1364 StoreSubscrListRevertsBackToStoreSubscrMonomorphicWhenNegativeKeyObserved) { 1365 HandleScope scope(thread_); 1366 ASSERT_FALSE(runFromCStr(runtime_, R"( 1367def foo(l, i): 1368 l[i] = 5 1369 return l[i] 1370 1371l = [1,2,3] 1372)") 1373 .isError()); 1374 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1375 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1376 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_ANAMORPHIC); 1377 1378 List l(&scope, mainModuleAt(runtime_, "l")); 1379 SmallInt key(&scope, SmallInt::fromWord(1)); 1380 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 5)); 1381 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_LIST); 1382 1383 // Revert back to caching __getitem__ when the key is negative. 1384 SmallInt negative(&scope, SmallInt::fromWord(-1)); 1385 EXPECT_TRUE( 1386 isIntEqualsWord(Interpreter::call2(thread_, foo, l, negative), 5)); 1387 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_MONOMORPHIC); 1388} 1389 1390TEST_F(InterpreterTest, BinarySubscrWithTupleAndSmallInt) { 1391 HandleScope scope(thread_); 1392 ASSERT_FALSE(runFromCStr(runtime_, R"( 1393def foo(l, i): 1394 return l[i] 1395 1396l = (1,2,3) 1397)") 1398 .isError()); 1399 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1400 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1401 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1402 1403 Tuple l(&scope, mainModuleAt(runtime_, "l")); 1404 SmallInt zero(&scope, SmallInt::fromWord(0)); 1405 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, zero), 1)); 1406 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_TUPLE); 1407 1408 SmallInt one(&scope, SmallInt::fromWord(1)); 1409 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, one), 2)); 1410 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_TUPLE); 1411} 1412 1413TEST_F( 1414 InterpreterTest, 1415 BinarySubscrTupleRevertsBackToBinarySubscrMonomorphicWhenNonTupleObserved) { 1416 HandleScope scope(thread_); 1417 ASSERT_FALSE(runFromCStr(runtime_, R"( 1418def foo(l, i): 1419 return l[i] 1420 1421l = (1,2,3) 1422d = {1: -1} 1423)") 1424 .isError()); 1425 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1426 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1427 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1428 1429 Tuple l(&scope, mainModuleAt(runtime_, "l")); 1430 SmallInt key(&scope, SmallInt::fromWord(1)); 1431 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 2)); 1432 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_TUPLE); 1433 1434 // Revert back to caching __getitem__ when a non-list is observed. 1435 Dict d(&scope, mainModuleAt(runtime_, "d")); 1436 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, d, key), -1)); 1437 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1438} 1439 1440TEST_F( 1441 InterpreterTest, 1442 BinarySubscrTupleRevertsBackToBinarySubscrMonomorphicWhenNonSmallIntKeyObserved) { 1443 HandleScope scope(thread_); 1444 ASSERT_FALSE(runFromCStr(runtime_, R"( 1445def foo(l, i): 1446 return l[i] 1447 1448l = (1,2,3) 1449large_int = 2**64 1450)") 1451 .isError()); 1452 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1453 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1454 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1455 1456 Tuple l(&scope, mainModuleAt(runtime_, "l")); 1457 SmallInt key(&scope, SmallInt::fromWord(1)); 1458 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 2)); 1459 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_TUPLE); 1460 1461 // Revert back to caching __getitem__ when the key is not SmallInt. 1462 LargeInt large_int(&scope, mainModuleAt(runtime_, "large_int")); 1463 EXPECT_TRUE(Interpreter::call2(thread_, foo, l, large_int).isError()); 1464 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1465} 1466 1467TEST_F( 1468 InterpreterTest, 1469 BinarySubscrTupleRevertsBackToBinarySubscrMonomorphicWhenNegativeKeyObserved) { 1470 HandleScope scope(thread_); 1471 ASSERT_FALSE(runFromCStr(runtime_, R"( 1472def foo(l, i): 1473 return l[i] 1474 1475l = (1,2,3) 1476)") 1477 .isError()); 1478 Function foo(&scope, mainModuleAt(runtime_, "foo")); 1479 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 1480 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_ANAMORPHIC); 1481 1482 Tuple l(&scope, mainModuleAt(runtime_, "l")); 1483 SmallInt key(&scope, SmallInt::fromWord(1)); 1484 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 2)); 1485 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_TUPLE); 1486 1487 // Revert back to caching __getitem__ when the key is negative. 1488 SmallInt negative(&scope, SmallInt::fromWord(-1)); 1489 EXPECT_TRUE( 1490 isIntEqualsWord(Interpreter::call2(thread_, foo, l, negative), 3)); 1491 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), BINARY_SUBSCR_MONOMORPHIC); 1492} 1493 1494TEST_F(InterpreterTest, InplaceOpCachedInsertsDependencyForThreeAttributes) { 1495 HandleScope scope(thread_); 1496 EXPECT_FALSE(runFromCStr(runtime_, R"( 1497class A: 1498 def __imul__(self, other): 1499 return "from class A" 1500 1501class B: 1502 pass 1503 1504def cache_inplace_op(a, b): 1505 a *= b 1506 1507a = A() 1508b = B() 1509A__imul__ = A.__imul__ 1510cache_inplace_op(a, b) 1511)") 1512 .isError()); 1513 Function cache_inplace_op(&scope, mainModuleAt(runtime_, "cache_inplace_op")); 1514 MutableTuple caches(&scope, cache_inplace_op.caches()); 1515 Object a(&scope, mainModuleAt(runtime_, "a")); 1516 Object b(&scope, mainModuleAt(runtime_, "b")); 1517 Type type_a(&scope, mainModuleAt(runtime_, "A")); 1518 Type type_b(&scope, mainModuleAt(runtime_, "B")); 1519 BinaryOpFlags flag; 1520 ASSERT_EQ(icLookupBinaryOp(*caches, 0, a.layoutId(), b.layoutId(), &flag), 1521 mainModuleAt(runtime_, "A__imul__")); 1522 1523 // Verify that A.__imul__ has the dependent. 1524 Object inplace_op_name(&scope, runtime_->symbols()->at(ID(__imul__))); 1525 Object inplace_attr(&scope, typeValueCellAt(*type_a, *inplace_op_name)); 1526 ASSERT_TRUE(inplace_attr.isValueCell()); 1527 ASSERT_TRUE(ValueCell::cast(*inplace_attr).dependencyLink().isWeakLink()); 1528 EXPECT_EQ(WeakLink::cast(ValueCell::cast(*inplace_attr).dependencyLink()) 1529 .referent(), 1530 *cache_inplace_op); 1531 1532 // Verify that A.__mul__ has the dependent. 1533 Object left_op_name(&scope, runtime_->symbols()->at(ID(__mul__))); 1534 Object type_a_attr(&scope, typeValueCellAt(*type_a, *left_op_name)); 1535 ASSERT_TRUE(type_a_attr.isValueCell()); 1536 ASSERT_TRUE(ValueCell::cast(*type_a_attr).dependencyLink().isWeakLink()); 1537 EXPECT_EQ( 1538 WeakLink::cast(ValueCell::cast(*type_a_attr).dependencyLink()).referent(), 1539 *cache_inplace_op); 1540 1541 // Verify that B.__rmul__ has the dependent. 1542 Object right_op_name(&scope, runtime_->symbols()->at(ID(__rmul__))); 1543 Object type_b_attr(&scope, typeValueCellAt(*type_b, *right_op_name)); 1544 ASSERT_TRUE(type_b_attr.isValueCell()); 1545 ASSERT_TRUE(ValueCell::cast(*type_b_attr).dependencyLink().isWeakLink()); 1546 EXPECT_EQ( 1547 WeakLink::cast(ValueCell::cast(*type_b_attr).dependencyLink()).referent(), 1548 *cache_inplace_op); 1549} 1550 1551TEST_F(InterpreterTest, ImportFromWithMissingAttributeRaisesImportError) { 1552 HandleScope scope(thread_); 1553 Str name(&scope, runtime_->newStrFromCStr("foo")); 1554 Module module(&scope, runtime_->newModule(name)); 1555 Object modules(&scope, runtime_->modules()); 1556 ASSERT_FALSE( 1557 objectSetItem(thread_, modules, name, module).isErrorException()); 1558 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "from foo import bar"), 1559 LayoutId::kImportError, 1560 "cannot import name 'bar' from 'foo'")); 1561} 1562 1563TEST_F(InterpreterTest, ImportFromCallsDunderGetattribute) { 1564 HandleScope scope(thread_); 1565 ASSERT_FALSE(runFromCStr(runtime_, R"( 1566class C: 1567 def __getattribute__(self, name): 1568 return f"getattribute '{name}'" 1569i = C() 1570)") 1571 .isError()); 1572 Object i(&scope, mainModuleAt(runtime_, "i")); 1573 1574 Tuple consts(&scope, runtime_->newTupleWith1(i)); 1575 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1576 Tuple names(&scope, runtime_->newTupleWith1(name)); 1577 const byte bytecode[] = {LOAD_CONST, 0, IMPORT_FROM, 0, RETURN_VALUE, 0}; 1578 Code code(&scope, newCodeWithBytesConstsNames(bytecode, consts, names)); 1579 1580 EXPECT_TRUE(isStrEqualsCStr(runCode(code), "getattribute 'foo'")); 1581} 1582 1583TEST_F(InterpreterTest, ImportFromWithNonModuleRaisesImportError) { 1584 HandleScope scope(thread_); 1585 Object obj(&scope, NoneType::object()); 1586 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 1587 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1588 Tuple names(&scope, runtime_->newTupleWith1(name)); 1589 const byte bytecode[] = {LOAD_CONST, 0, IMPORT_FROM, 0, RETURN_VALUE, 0}; 1590 Code code(&scope, newCodeWithBytesConstsNames(bytecode, consts, names)); 1591 1592 EXPECT_TRUE(raisedWithStr(runCode(code), LayoutId::kImportError, 1593 "cannot import name 'foo'")); 1594} 1595 1596TEST_F(InterpreterTest, ImportFromWithNonModulePropagatesException) { 1597 HandleScope scope(thread_); 1598 ASSERT_FALSE(runFromCStr(runtime_, R"( 1599class C: 1600 def __getattribute__(self, name): 1601 raise UserWarning() 1602i = C() 1603)") 1604 .isError()); 1605 Object i(&scope, mainModuleAt(runtime_, "i")); 1606 1607 Tuple consts(&scope, runtime_->newTupleWith1(i)); 1608 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1609 Tuple names(&scope, runtime_->newTupleWith1(name)); 1610 const byte bytecode[] = {LOAD_CONST, 0, IMPORT_FROM, 0, RETURN_VALUE, 0}; 1611 Code code(&scope, newCodeWithBytesConstsNames(bytecode, consts, names)); 1612 1613 EXPECT_TRUE(raised(runCode(code), LayoutId::kUserWarning)); 1614} 1615 1616TEST_F(InterpreterTest, InplaceOperationCallsInplaceMethod) { 1617 HandleScope scope(thread_); 1618 1619 ASSERT_FALSE(runFromCStr(runtime_, R"( 1620class C: 1621 def __isub__(self, other): 1622 return (C, '__isub__', self, other) 1623 1624left = C() 1625right = C() 1626)") 1627 .isError()); 1628 1629 Object left(&scope, mainModuleAt(runtime_, "left")); 1630 Object right(&scope, mainModuleAt(runtime_, "right")); 1631 Object c_class(&scope, mainModuleAt(runtime_, "C")); 1632 1633 Object result_obj( 1634 &scope, Interpreter::inplaceOperation(thread_, Interpreter::BinaryOp::SUB, 1635 left, right)); 1636 ASSERT_TRUE(result_obj.isTuple()); 1637 Tuple result(&scope, *result_obj); 1638 ASSERT_EQ(result.length(), 4); 1639 EXPECT_EQ(result.at(0), *c_class); 1640 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "__isub__")); 1641 EXPECT_EQ(result.at(2), *left); 1642 EXPECT_EQ(result.at(3), *right); 1643} 1644 1645TEST_F(InterpreterTest, InplaceOperationCallsBinaryMethod) { 1646 HandleScope scope(thread_); 1647 1648 ASSERT_FALSE(runFromCStr(runtime_, R"( 1649class C: 1650 def __sub__(self, other): 1651 return (C, '__sub__', self, other) 1652 1653left = C() 1654right = C() 1655)") 1656 .isError()); 1657 1658 Object left(&scope, mainModuleAt(runtime_, "left")); 1659 Object right(&scope, mainModuleAt(runtime_, "right")); 1660 Object c_class(&scope, mainModuleAt(runtime_, "C")); 1661 1662 Object result_obj( 1663 &scope, Interpreter::inplaceOperation(thread_, Interpreter::BinaryOp::SUB, 1664 left, right)); 1665 ASSERT_TRUE(result_obj.isTuple()); 1666 Tuple result(&scope, *result_obj); 1667 ASSERT_EQ(result.length(), 4); 1668 EXPECT_EQ(result.at(0), *c_class); 1669 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "__sub__")); 1670 EXPECT_EQ(result.at(2), *left); 1671 EXPECT_EQ(result.at(3), *right); 1672} 1673 1674TEST_F(InterpreterTest, InplaceOperationCallsBinaryMethodAfterNotImplemented) { 1675 HandleScope scope(thread_); 1676 1677 ASSERT_FALSE(runFromCStr(runtime_, R"( 1678class C: 1679 def __isub__(self, other): 1680 return NotImplemented 1681 def __sub__(self, other): 1682 return (C, '__sub__', self, other) 1683 1684left = C() 1685right = C() 1686)") 1687 .isError()); 1688 1689 Object left(&scope, mainModuleAt(runtime_, "left")); 1690 Object right(&scope, mainModuleAt(runtime_, "right")); 1691 Object c_class(&scope, mainModuleAt(runtime_, "C")); 1692 1693 Object result_obj( 1694 &scope, Interpreter::inplaceOperation(thread_, Interpreter::BinaryOp::SUB, 1695 left, right)); 1696 ASSERT_TRUE(result_obj.isTuple()); 1697 Tuple result(&scope, *result_obj); 1698 ASSERT_EQ(result.length(), 4); 1699 EXPECT_EQ(result.at(0), *c_class); 1700 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "__sub__")); 1701 EXPECT_EQ(result.at(2), *left); 1702 EXPECT_EQ(result.at(3), *right); 1703} 1704 1705TEST_F(InterpreterTest, InplaceOperationSetMethodSetsMethodFlagsBinaryOpRetry) { 1706 HandleScope scope(thread_); 1707 ASSERT_FALSE(runFromCStr(runtime_, R"( 1708class MyInt(int): 1709 def __isub__(self, other): 1710 return int(self) - other - 2 1711v0 = MyInt(9) 1712v1 = MyInt(-11) 1713v2 = MyInt(-3) 1714v3 = MyInt(7) 1715)") 1716 .isError()); 1717 Object v0(&scope, mainModuleAt(runtime_, "v0")); 1718 Object v1(&scope, mainModuleAt(runtime_, "v1")); 1719 Object v2(&scope, mainModuleAt(runtime_, "v2")); 1720 Object v3(&scope, mainModuleAt(runtime_, "v3")); 1721 Object method(&scope, NoneType::object()); 1722 BinaryOpFlags flags; 1723 EXPECT_TRUE(isIntEqualsWord( 1724 Interpreter::inplaceOperationSetMethod( 1725 thread_, Interpreter::BinaryOp::SUB, v0, v1, &method, &flags), 1726 18)); 1727 EXPECT_EQ(flags, kInplaceBinaryOpRetry); 1728 1729 ASSERT_EQ(v0.layoutId(), v2.layoutId()); 1730 ASSERT_EQ(v1.layoutId(), v3.layoutId()); 1731 EXPECT_TRUE(isIntEqualsWord( 1732 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *v2, *v3), 1733 -12)); 1734} 1735 1736TEST_F(InterpreterTest, InplaceOperationSetMethodSetsMethodFlagsReverseRetry) { 1737 HandleScope scope(thread_); 1738 ASSERT_FALSE(runFromCStr(runtime_, R"( 1739class MyInt(int): 1740 pass 1741class MyIntSub(MyInt): 1742 def __rpow__(self, other): 1743 return int(other) ** int(self) - 7 1744v0 = MyInt(3) 1745v1 = MyIntSub(3) 1746v2 = MyInt(-4) 1747v3 = MyIntSub(4) 1748)") 1749 .isError()); 1750 Object v0(&scope, mainModuleAt(runtime_, "v0")); 1751 Object v1(&scope, mainModuleAt(runtime_, "v1")); 1752 Object v2(&scope, mainModuleAt(runtime_, "v2")); 1753 Object v3(&scope, mainModuleAt(runtime_, "v3")); 1754 Object method(&scope, NoneType::object()); 1755 BinaryOpFlags flags; 1756 EXPECT_TRUE(isIntEqualsWord( 1757 Interpreter::inplaceOperationSetMethod( 1758 thread_, Interpreter::BinaryOp::POW, v0, v1, &method, &flags), 1759 20)); 1760 EXPECT_EQ(flags, kBinaryOpReflected | kBinaryOpNotImplementedRetry); 1761 1762 ASSERT_EQ(v0.layoutId(), v2.layoutId()); 1763 ASSERT_EQ(v1.layoutId(), v3.layoutId()); 1764 EXPECT_TRUE(isIntEqualsWord( 1765 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *v2, *v3), 1766 249)); 1767} 1768 1769TEST_F(InterpreterTest, InplaceAddWithSmallIntsRewritesOpcode) { 1770 HandleScope scope(thread_); 1771 1772 word left = 7; 1773 word right = -13; 1774 Object left_obj(&scope, runtime_->newInt(left)); 1775 Object right_obj(&scope, runtime_->newInt(right)); 1776 Tuple consts(&scope, runtime_->newTupleWith2(left_obj, right_obj)); 1777 const byte bytecode[] = { 1778 LOAD_CONST, 0, LOAD_CONST, 1, INPLACE_ADD, 0, RETURN_VALUE, 0, 1779 }; 1780 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 1781 1782 Object qualname(&scope, Str::empty()); 1783 Module module(&scope, findMainModule(runtime_)); 1784 Function function( 1785 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 1786 1787 // Update the opcode. 1788 ASSERT_TRUE( 1789 isIntEqualsWord(Interpreter::call0(thread_, function), left + right)); 1790 1791 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 1792 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), INPLACE_ADD_SMALLINT); 1793 1794 // Updated opcode returns the same value. 1795 EXPECT_TRUE( 1796 isIntEqualsWord(Interpreter::call0(thread_, function), left + right)); 1797} 1798 1799TEST_F(InterpreterTest, InplaceAddSmallInt) { 1800 HandleScope scope(thread_); 1801 ASSERT_FALSE(runFromCStr(runtime_, R"( 1802def foo(a, b): 1803 a += b 1804 return a 1805)") 1806 .isError()); 1807 Function function(&scope, mainModuleAt(runtime_, "foo")); 1808 MutableBytes rewritten(&scope, function.rewrittenBytecode()); 1809 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), INPLACE_OP_ANAMORPHIC); 1810 1811 SmallInt left(&scope, SmallInt::fromWord(7)); 1812 SmallInt right(&scope, SmallInt::fromWord(-13)); 1813 1814 rewrittenBytecodeOpAtPut(rewritten, 2, INPLACE_ADD_SMALLINT); 1815 left = SmallInt::fromWord(7); 1816 right = SmallInt::fromWord(-13); 1817 // 7 + (-13) 1818 EXPECT_TRUE( 1819 isIntEqualsWord(Interpreter::call2(thread_, function, left, right), -6)); 1820} 1821 1822TEST_F(InterpreterTest, InplaceAddSmallIntRevertsBackToInplaceOp) { 1823 HandleScope scope(thread_); 1824 ASSERT_FALSE(runFromCStr(runtime_, R"( 1825def foo(a, b): 1826 a += b 1827 return a 1828)") 1829 .isError()); 1830 Function function(&scope, mainModuleAt(runtime_, "foo")); 1831 MutableBytes rewritten(&scope, function.rewrittenBytecode()); 1832 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), INPLACE_OP_ANAMORPHIC); 1833 1834 LargeInt left(&scope, runtime_->newInt(SmallInt::kMaxValue + 1)); 1835 SmallInt right(&scope, SmallInt::fromWord(13)); 1836 1837 rewrittenBytecodeOpAtPut(rewritten, 2, INPLACE_ADD_SMALLINT); 1838 // LARGE_SMALL_INT += SMALL_INT 1839 EXPECT_TRUE( 1840 isIntEqualsWord(Interpreter::call2(thread_, function, left, right), 1841 SmallInt::kMaxValue + 1 + 13)); 1842 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), INPLACE_OP_MONOMORPHIC); 1843} 1844 1845TEST_F(InterpreterTest, InplaceSubtractWithSmallIntsRewritesOpcode) { 1846 HandleScope scope(thread_); 1847 1848 word left = 7; 1849 word right = -13; 1850 Object left_obj(&scope, runtime_->newInt(left)); 1851 Object right_obj(&scope, runtime_->newInt(right)); 1852 Tuple consts(&scope, runtime_->newTupleWith2(left_obj, right_obj)); 1853 const byte bytecode[] = { 1854 LOAD_CONST, 0, LOAD_CONST, 1, INPLACE_SUBTRACT, 0, RETURN_VALUE, 0, 1855 }; 1856 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 1857 1858 Object qualname(&scope, Str::empty()); 1859 Module module(&scope, findMainModule(runtime_)); 1860 Function function( 1861 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 1862 1863 // Update the opcode. 1864 ASSERT_TRUE( 1865 isIntEqualsWord(Interpreter::call0(thread_, function), left - right)); 1866 1867 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 1868 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), INPLACE_SUB_SMALLINT); 1869 1870 // Updated opcode returns the same value. 1871 EXPECT_TRUE( 1872 isIntEqualsWord(Interpreter::call0(thread_, function), left - right)); 1873} 1874 1875TEST_F(InterpreterTest, InplaceSubtractSmallInt) { 1876 HandleScope scope(thread_); 1877 ASSERT_FALSE(runFromCStr(runtime_, R"( 1878def foo(a, b): 1879 a -= b 1880 return a 1881)") 1882 .isError()); 1883 Function function(&scope, mainModuleAt(runtime_, "foo")); 1884 MutableBytes rewritten(&scope, function.rewrittenBytecode()); 1885 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), INPLACE_OP_ANAMORPHIC); 1886 1887 SmallInt left(&scope, SmallInt::fromWord(7)); 1888 SmallInt right(&scope, SmallInt::fromWord(-13)); 1889 1890 rewrittenBytecodeOpAtPut(rewritten, 2, INPLACE_SUB_SMALLINT); 1891 left = SmallInt::fromWord(7); 1892 right = SmallInt::fromWord(-13); 1893 // 7 - (-13) 1894 EXPECT_TRUE( 1895 isIntEqualsWord(Interpreter::call2(thread_, function, left, right), 20)); 1896} 1897 1898TEST_F(InterpreterTest, InplaceSubSmallIntRevertsBackToInplaceOp) { 1899 HandleScope scope(thread_); 1900 ASSERT_FALSE(runFromCStr(runtime_, R"( 1901def foo(a, b): 1902 a -= b 1903 return a 1904)") 1905 .isError()); 1906 Function function(&scope, mainModuleAt(runtime_, "foo")); 1907 MutableBytes rewritten(&scope, function.rewrittenBytecode()); 1908 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), INPLACE_OP_ANAMORPHIC); 1909 1910 LargeInt left(&scope, runtime_->newInt(SmallInt::kMaxValue + 1)); 1911 SmallInt right(&scope, SmallInt::fromWord(13)); 1912 1913 rewrittenBytecodeOpAtPut(rewritten, 2, INPLACE_SUB_SMALLINT); 1914 // LARGE_SMALL_INT -= SMALL_INT 1915 EXPECT_TRUE( 1916 isIntEqualsWord(Interpreter::call2(thread_, function, left, right), 1917 SmallInt::kMaxValue + 1 - 13)); 1918 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), INPLACE_OP_MONOMORPHIC); 1919} 1920 1921TEST_F(InterpreterDeathTest, InvalidOpcode) { 1922 HandleScope scope(thread_); 1923 1924 const byte bytecode[] = {NOP, 0, NOP, 0, UNUSED_BYTECODE_0, 17, NOP, 7}; 1925 Code code(&scope, newCodeWithBytes(bytecode)); 1926 1927 ASSERT_DEATH(static_cast<void>(runCode(code)), 1928 "bytecode 'UNUSED_BYTECODE_0'"); 1929} 1930 1931TEST_F(InterpreterTest, CallDescriptorGetWithBuiltinTypeDescriptors) { 1932 ASSERT_FALSE(runFromCStr(runtime_, R"( 1933 1934def class_method_func(self): pass 1935 1936def static_method_func(cls): pass 1937 1938class C: 1939 class_method = classmethod(class_method_func) 1940 1941 static_method = staticmethod(static_method_func) 1942 1943 @property 1944 def property_field(self): return "property" 1945 1946 def function_field(self): pass 1947 1948i = C() 1949)") 1950 .isError()); 1951 HandleScope scope(thread_); 1952 Type c(&scope, mainModuleAt(runtime_, "C")); 1953 Type type(&scope, runtime_->typeOf(*c)); 1954 Object i(&scope, mainModuleAt(runtime_, "i")); 1955 1956 Object class_method_name(&scope, 1957 Runtime::internStrFromCStr(thread_, "class_method")); 1958 Object class_method(&scope, typeAt(c, class_method_name)); 1959 BoundMethod class_method_result( 1960 &scope, Interpreter::callDescriptorGet(thread_, class_method, i, c)); 1961 EXPECT_EQ(class_method_result.self(), *c); 1962 EXPECT_EQ(class_method_result.function(), 1963 mainModuleAt(runtime_, "class_method_func")); 1964 1965 Object static_method_name( 1966 &scope, Runtime::internStrFromCStr(thread_, "static_method")); 1967 Object static_method(&scope, typeAt(c, static_method_name)); 1968 Function static_method_result( 1969 &scope, Interpreter::callDescriptorGet(thread_, static_method, c, type)); 1970 EXPECT_EQ(*static_method_result, 1971 mainModuleAt(runtime_, "static_method_func")); 1972 1973 Object property_field_name( 1974 &scope, Runtime::internStrFromCStr(thread_, "property_field")); 1975 Object property_field(&scope, typeAt(c, property_field_name)); 1976 Object property_field_result( 1977 &scope, Interpreter::callDescriptorGet(thread_, property_field, i, c)); 1978 EXPECT_TRUE(isStrEqualsCStr(*property_field_result, "property")); 1979 1980 Object function_field_name( 1981 &scope, Runtime::internStrFromCStr(thread_, "function_field")); 1982 Object function_field(&scope, typeAt(c, function_field_name)); 1983 BoundMethod function_field_result( 1984 &scope, Interpreter::callDescriptorGet(thread_, function_field, i, c)); 1985 EXPECT_EQ(function_field_result.self(), *i); 1986 EXPECT_EQ(function_field_result.function(), *function_field); 1987 1988 Object none(&scope, NoneType::object()); 1989 Function function_field_result_from_none_instance( 1990 &scope, Interpreter::callDescriptorGet(thread_, function_field, none, c)); 1991 EXPECT_EQ(function_field_result_from_none_instance, *function_field); 1992 1993 Type none_type(&scope, runtime_->typeAt(LayoutId::kNoneType)); 1994 BoundMethod function_field_result_from_none_instance_of_none_type( 1995 &scope, 1996 Interpreter::callDescriptorGet(thread_, function_field, none, none_type)); 1997 EXPECT_EQ(function_field_result_from_none_instance_of_none_type.self(), 1998 *none); 1999 EXPECT_EQ(function_field_result_from_none_instance_of_none_type.function(), 2000 *function_field); 2001} 2002 2003TEST_F(InterpreterTest, CompareInAnamorphicWithStrRewritesOpcode) { 2004 HandleScope scope(thread_); 2005 Object obj1(&scope, runtime_->newStrFromCStr("test")); 2006 Object obj2(&scope, runtime_->newStrFromCStr("test string")); 2007 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2)); 2008 const byte bytecode[] = { 2009 LOAD_CONST, 0, LOAD_CONST, 1, COMPARE_IN_ANAMORPHIC, 0, RETURN_VALUE, 0, 2010 }; 2011 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2012 2013 Object qualname(&scope, Str::empty()); 2014 Module module(&scope, findMainModule(runtime_)); 2015 Function function( 2016 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 2017 2018 // Update the opcode. 2019 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2020 2021 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 2022 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), COMPARE_IN_STR); 2023 2024 // Updated opcode returns the same value. 2025 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2026} 2027 2028TEST_F(InterpreterTest, CompareInAnamorphicWithDictRewritesOpcode) { 2029 HandleScope scope(thread_); 2030 Dict dict(&scope, runtime_->newDict()); 2031 Str key(&scope, runtime_->newStrFromCStr("test")); 2032 word key_hash = strHash(thread_, *key); 2033 dictAtPut(thread_, dict, key, key_hash, key); 2034 Tuple consts(&scope, runtime_->newTupleWith2(key, dict)); 2035 const byte bytecode[] = { 2036 LOAD_CONST, 0, LOAD_CONST, 1, COMPARE_IN_ANAMORPHIC, 0, RETURN_VALUE, 0, 2037 }; 2038 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2039 2040 Object qualname(&scope, Str::empty()); 2041 Module module(&scope, findMainModule(runtime_)); 2042 Function function( 2043 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 2044 2045 // Update the opcode. 2046 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2047 2048 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 2049 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), COMPARE_IN_DICT); 2050 2051 // Updated opcode returns the same value. 2052 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2053} 2054 2055TEST_F(InterpreterTest, CompareInAnamorphicWithTupleRewritesOpcode) { 2056 HandleScope scope(thread_); 2057 Object obj(&scope, runtime_->newStrFromCStr("test")); 2058 Tuple tuple(&scope, runtime_->newTupleWith1(obj)); 2059 Tuple consts(&scope, runtime_->newTupleWith2(obj, tuple)); 2060 const byte bytecode[] = { 2061 LOAD_CONST, 0, LOAD_CONST, 1, COMPARE_IN_ANAMORPHIC, 0, RETURN_VALUE, 0, 2062 }; 2063 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2064 2065 Object qualname(&scope, Str::empty()); 2066 Module module(&scope, findMainModule(runtime_)); 2067 Function function( 2068 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 2069 2070 // Update the opcode. 2071 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2072 2073 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 2074 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), COMPARE_IN_TUPLE); 2075 2076 // Updated opcode returns the same value. 2077 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2078} 2079 2080TEST_F(InterpreterTest, CompareInAnamorphicWithListRewritesOpcode) { 2081 HandleScope scope(thread_); 2082 List list(&scope, runtime_->newList()); 2083 Object value0(&scope, runtime_->newStrFromCStr("value0")); 2084 Object value1(&scope, runtime_->newStrFromCStr("test")); 2085 listInsert(thread_, list, value0, 0); 2086 listInsert(thread_, list, value1, 1); 2087 Tuple consts(&scope, runtime_->newTupleWith2(value1, list)); 2088 const byte bytecode[] = { 2089 LOAD_CONST, 0, LOAD_CONST, 1, COMPARE_IN_ANAMORPHIC, 0, RETURN_VALUE, 0, 2090 }; 2091 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2092 2093 Object qualname(&scope, Str::empty()); 2094 Module module(&scope, findMainModule(runtime_)); 2095 Function function( 2096 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 2097 2098 // Update the opcode. 2099 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2100 2101 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 2102 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), COMPARE_IN_LIST); 2103 2104 // Updated opcode returns the same value. 2105 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2106} 2107 2108// To a rich comparison on two instances of the same type. In each case, the 2109// method on the left side of the comparison should be used. 2110TEST_F(InterpreterTest, CompareOpSameType) { 2111 HandleScope scope(thread_); 2112 2113 ASSERT_FALSE(runFromCStr(runtime_, R"( 2114class C: 2115 def __init__(self, value): 2116 self.value = value 2117 2118 def __lt__(self, other): 2119 return self.value < other.value 2120 2121c10 = C(10) 2122c20 = C(20) 2123)") 2124 .isError()); 2125 2126 Object left(&scope, mainModuleAt(runtime_, "c10")); 2127 Object right(&scope, mainModuleAt(runtime_, "c20")); 2128 2129 Object left_lt_right(&scope, Interpreter::compareOperation( 2130 thread_, CompareOp::LT, left, right)); 2131 EXPECT_EQ(left_lt_right, Bool::trueObj()); 2132 2133 Object right_lt_left(&scope, Interpreter::compareOperation( 2134 thread_, CompareOp::LT, right, left)); 2135 EXPECT_EQ(right_lt_left, Bool::falseObj()); 2136} 2137 2138TEST_F(InterpreterTest, CompareOpFallback) { 2139 HandleScope scope(thread_); 2140 2141 ASSERT_FALSE(runFromCStr(runtime_, R"( 2142class C: 2143 def __init__(self, value): 2144 self.value = value 2145 2146c10 = C(10) 2147c20 = C(20) 2148)") 2149 .isError()); 2150 2151 Object left(&scope, mainModuleAt(runtime_, "c10")); 2152 Object right(&scope, mainModuleAt(runtime_, "c20")); 2153 2154 Object left_eq_right(&scope, Interpreter::compareOperation( 2155 thread_, CompareOp::EQ, left, right)); 2156 EXPECT_EQ(left_eq_right, Bool::falseObj()); 2157 Object left_ne_right(&scope, Interpreter::compareOperation( 2158 thread_, CompareOp::NE, left, right)); 2159 EXPECT_EQ(left_ne_right, Bool::trueObj()); 2160 2161 Object right_eq_left(&scope, Interpreter::compareOperation( 2162 thread_, CompareOp::EQ, left, right)); 2163 EXPECT_EQ(right_eq_left, Bool::falseObj()); 2164 Object right_ne_left(&scope, Interpreter::compareOperation( 2165 thread_, CompareOp::NE, left, right)); 2166 EXPECT_EQ(right_ne_left, Bool::trueObj()); 2167} 2168 2169TEST_F(InterpreterTest, CompareOpSubclass) { 2170 HandleScope scope(thread_); 2171 2172 ASSERT_FALSE(runFromCStr(runtime_, R"( 2173called = None 2174class A: 2175 def __eq__(self, other): 2176 global called 2177 if (called is not None): 2178 called = "ERROR" 2179 else: 2180 called = "A" 2181 return False 2182 2183class B: 2184 def __eq__(self, other): 2185 global called 2186 if (called is not None): 2187 called = "ERROR" 2188 else: 2189 called = "B" 2190 return True 2191 2192class C(A): 2193 def __eq__(self, other): 2194 global called 2195 if (called is not None): 2196 called = "ERROR" 2197 else: 2198 called = "C" 2199 return True 2200 2201a = A() 2202b = B() 2203c = C() 2204)") 2205 .isError()); 2206 2207 Object a(&scope, mainModuleAt(runtime_, "a")); 2208 Object b(&scope, mainModuleAt(runtime_, "b")); 2209 Object c(&scope, mainModuleAt(runtime_, "c")); 2210 2211 // Comparisons where rhs is not a subtype of lhs try lhs.__eq__(rhs) first. 2212 Object a_eq_b(&scope, 2213 Interpreter::compareOperation(thread_, CompareOp::EQ, a, b)); 2214 EXPECT_EQ(a_eq_b, Bool::falseObj()); 2215 Object called(&scope, mainModuleAt(runtime_, "called")); 2216 EXPECT_TRUE(isStrEqualsCStr(*called, "A")); 2217 2218 Object called_name(&scope, Runtime::internStrFromCStr(thread_, "called")); 2219 Object none(&scope, NoneType::object()); 2220 Module main(&scope, findMainModule(runtime_)); 2221 moduleAtPut(thread_, main, called_name, none); 2222 Object b_eq_a(&scope, 2223 Interpreter::compareOperation(thread_, CompareOp::EQ, b, a)); 2224 EXPECT_EQ(b_eq_a, Bool::trueObj()); 2225 called = mainModuleAt(runtime_, "called"); 2226 EXPECT_TRUE(isStrEqualsCStr(*called, "B")); 2227 2228 moduleAtPut(thread_, main, called_name, none); 2229 Object c_eq_a(&scope, 2230 Interpreter::compareOperation(thread_, CompareOp::EQ, c, a)); 2231 EXPECT_EQ(c_eq_a, Bool::trueObj()); 2232 called = mainModuleAt(runtime_, "called"); 2233 EXPECT_TRUE(isStrEqualsCStr(*called, "C")); 2234 2235 // When rhs is a subtype of lhs, only rhs.__eq__(rhs) is tried. 2236 moduleAtPut(thread_, main, called_name, none); 2237 Object a_eq_c(&scope, 2238 Interpreter::compareOperation(thread_, CompareOp::EQ, a, c)); 2239 EXPECT_EQ(a_eq_c, Bool::trueObj()); 2240 called = mainModuleAt(runtime_, "called"); 2241 EXPECT_TRUE(isStrEqualsCStr(*called, "C")); 2242} 2243 2244TEST_F(InterpreterTest, CompareOpWithStrsRewritesOpcode) { 2245 HandleScope scope(thread_); 2246 2247 Object obj1(&scope, runtime_->newStrFromCStr("abc")); 2248 Object obj2(&scope, runtime_->newStrFromCStr("def")); 2249 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2)); 2250 const byte bytecode[] = { 2251 LOAD_CONST, 0, 2252 LOAD_CONST, 1, 2253 COMPARE_OP, static_cast<byte>(CompareOp::EQ), 2254 RETURN_VALUE, 0, 2255 }; 2256 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2257 2258 Object qualname(&scope, Str::empty()); 2259 Module module(&scope, findMainModule(runtime_)); 2260 Function function( 2261 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 2262 2263 // Update the opcode. 2264 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::falseObj()); 2265 2266 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 2267 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), COMPARE_EQ_STR); 2268 2269 // Updated opcode returns the same value. 2270 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::falseObj()); 2271} 2272 2273TEST_F(InterpreterTest, CompareOpWithNeOperatorWithStrsRewritesToCompareNeStr) { 2274 HandleScope scope(thread_); 2275 2276 Object obj1(&scope, runtime_->newStrFromCStr("abc")); 2277 Object obj2(&scope, runtime_->newStrFromCStr("def")); 2278 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2)); 2279 const byte bytecode[] = { 2280 LOAD_CONST, 0, 2281 LOAD_CONST, 1, 2282 COMPARE_OP, static_cast<byte>(CompareOp::NE), 2283 RETURN_VALUE, 0, 2284 }; 2285 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2286 2287 Object qualname(&scope, Str::empty()); 2288 Module module(&scope, findMainModule(runtime_)); 2289 Function function( 2290 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 2291 2292 // Update the opcode. 2293 EXPECT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2294 2295 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 2296 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), COMPARE_NE_STR); 2297 2298 // Updated opcode returns the same value. 2299 EXPECT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2300 2301 // Revert the opcode back to COMPARE_OP_MONOMIRPHIC in case a non-str argument 2302 // is observed by evaluating `str_obj` != `tuple_obj`. 2303 consts.atPut(0, runtime_->emptyTuple()); 2304 EXPECT_EQ(Interpreter::call0(thread_, function), Bool::trueObj()); 2305 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), 2306 COMPARE_OP_MONOMORPHIC); 2307} 2308 2309TEST_F(InterpreterTest, CompareOpSmallIntsRewritesOpcode) { 2310 HandleScope scope(thread_); 2311 2312 word left = 7; 2313 word right = -13; 2314 Object obj1(&scope, runtime_->newInt(left)); 2315 Object obj2(&scope, runtime_->newInt(right)); 2316 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2)); 2317 const byte bytecode[] = { 2318 LOAD_CONST, 0, 2319 LOAD_CONST, 1, 2320 COMPARE_OP, static_cast<byte>(CompareOp::LT), 2321 RETURN_VALUE, 0, 2322 }; 2323 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2324 2325 Object qualname(&scope, Str::empty()); 2326 Module module(&scope, findMainModule(runtime_)); 2327 Function function( 2328 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 2329 2330 // Update the opcode. 2331 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::falseObj()); 2332 2333 MutableBytes rewritten_bytecode(&scope, function.rewrittenBytecode()); 2334 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten_bytecode, 2), COMPARE_LT_SMALLINT); 2335 2336 // Updated opcode returns the same value. 2337 ASSERT_EQ(Interpreter::call0(thread_, function), Bool::falseObj()); 2338} 2339 2340TEST_F(InterpreterTest, CompareOpWithSmallInts) { 2341 HandleScope scope(thread_); 2342 ASSERT_FALSE(runFromCStr(runtime_, R"( 2343def foo(a, b): 2344 return a == b 2345)") 2346 .isError()); 2347 Function function(&scope, mainModuleAt(runtime_, "foo")); 2348 MutableBytes rewritten(&scope, function.rewrittenBytecode()); 2349 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_OP_ANAMORPHIC); 2350 2351 SmallInt left(&scope, SmallInt::fromWord(7)); 2352 SmallInt right(&scope, SmallInt::fromWord(-13)); 2353 2354 rewrittenBytecodeOpAtPut(rewritten, 2, COMPARE_EQ_SMALLINT); 2355 left = SmallInt::fromWord(7); 2356 right = SmallInt::fromWord(-13); 2357 // 7 == -13 2358 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2359 Bool::falseObj()); 2360 // 7 == 7 2361 left = SmallInt::fromWord(7); 2362 right = SmallInt::fromWord(7); 2363 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2364 Bool::trueObj()); 2365 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_EQ_SMALLINT); 2366 2367 rewrittenBytecodeOpAtPut(rewritten, 2, COMPARE_NE_SMALLINT); 2368 left = SmallInt::fromWord(7); 2369 right = SmallInt::fromWord(7); 2370 // 7 != 7 2371 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2372 Bool::falseObj()); 2373 left = SmallInt::fromWord(7); 2374 right = SmallInt::fromWord(-13); 2375 // 7 != -13 2376 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2377 Bool::trueObj()); 2378 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_NE_SMALLINT); 2379 2380 rewrittenBytecodeOpAtPut(rewritten, 2, COMPARE_GT_SMALLINT); 2381 left = SmallInt::fromWord(10); 2382 right = SmallInt::fromWord(10); 2383 // 10 > 10 2384 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2385 Bool::falseObj()); 2386 left = SmallInt::fromWord(10); 2387 right = SmallInt::fromWord(-10); 2388 // 10 > -10 2389 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2390 Bool::trueObj()); 2391 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_GT_SMALLINT); 2392 2393 rewrittenBytecodeOpAtPut(rewritten, 2, COMPARE_GE_SMALLINT); 2394 left = SmallInt::fromWord(-10); 2395 right = SmallInt::fromWord(10); 2396 // -10 >= 10 2397 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2398 Bool::falseObj()); 2399 left = SmallInt::fromWord(10); 2400 right = SmallInt::fromWord(10); 2401 // 10 >= 10 2402 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2403 Bool::trueObj()); 2404 left = SmallInt::fromWord(11); 2405 right = SmallInt::fromWord(10); 2406 // 11 > = 10 2407 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2408 Bool::trueObj()); 2409 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_GE_SMALLINT); 2410 2411 rewrittenBytecodeOpAtPut(rewritten, 2, COMPARE_LT_SMALLINT); 2412 left = SmallInt::fromWord(10); 2413 right = SmallInt::fromWord(-10); 2414 // 10 < -10 2415 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2416 Bool::falseObj()); 2417 left = SmallInt::fromWord(-10); 2418 right = SmallInt::fromWord(10); 2419 // -10 < 10 2420 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2421 Bool::trueObj()); 2422 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_LT_SMALLINT); 2423 2424 rewrittenBytecodeOpAtPut(rewritten, 2, COMPARE_LE_SMALLINT); 2425 left = SmallInt::fromWord(10); 2426 right = SmallInt::fromWord(-10); 2427 // 10 <= -10 2428 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2429 Bool::falseObj()); 2430 left = SmallInt::fromWord(10); 2431 right = SmallInt::fromWord(10); 2432 // 10 <= 10 2433 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2434 Bool::trueObj()); 2435 left = SmallInt::fromWord(9); 2436 right = SmallInt::fromWord(10); 2437 // 9 <= 10 2438 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2439 Bool::trueObj()); 2440 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_LE_SMALLINT); 2441} 2442 2443TEST_F(InterpreterTest, CompareOpWithSmallIntsRevertsBackToCompareOp) { 2444 HandleScope scope(thread_); 2445 ASSERT_FALSE(runFromCStr(runtime_, R"( 2446def foo(a, b): 2447 return a == b 2448)") 2449 .isError()); 2450 Function function(&scope, mainModuleAt(runtime_, "foo")); 2451 MutableBytes rewritten(&scope, function.rewrittenBytecode()); 2452 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_OP_ANAMORPHIC); 2453 2454 LargeInt left(&scope, runtime_->newInt(SmallInt::kMaxValue + 1)); 2455 LargeInt right(&scope, runtime_->newInt(SmallInt::kMaxValue + 1)); 2456 2457 rewrittenBytecodeOpAtPut(rewritten, 2, COMPARE_EQ_SMALLINT); 2458 // LARGE_SMALL_INT == SMALL_INT 2459 EXPECT_EQ(Interpreter::call2(thread_, function, left, right), 2460 Bool::trueObj()); 2461 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 2), COMPARE_OP_MONOMORPHIC); 2462} 2463 2464TEST_F(InterpreterTest, CompareOpSetMethodSetsMethod) { 2465 HandleScope scope(thread_); 2466 Object v0(&scope, runtime_->newInt(39)); 2467 Object v1(&scope, runtime_->newInt(11)); 2468 Object method(&scope, NoneType::object()); 2469 BinaryOpFlags flags; 2470 EXPECT_EQ(Interpreter::compareOperationSetMethod(thread_, CompareOp::LT, v0, 2471 v1, &method, &flags), 2472 Bool::falseObj()); 2473 EXPECT_TRUE(method.isFunction()); 2474 EXPECT_EQ(flags, kBinaryOpNotImplementedRetry); 2475 2476 Object v2(&scope, runtime_->newInt(3)); 2477 Object v3(&scope, runtime_->newInt(8)); 2478 ASSERT_EQ(v0.layoutId(), v2.layoutId()); 2479 ASSERT_EQ(v1.layoutId(), v3.layoutId()); 2480 EXPECT_EQ( 2481 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *v2, *v3), 2482 Bool::trueObj()); 2483} 2484 2485TEST_F(InterpreterTest, CompareOpSetMethodSetsReverseMethod) { 2486 HandleScope scope(thread_); 2487 ASSERT_FALSE(runFromCStr(runtime_, R"( 2488class A: 2489 pass 2490 2491class B(A): 2492 def __ge__(self, other): 2493 return (self, other) 2494 2495a1 = A() 2496b1 = B() 2497a2 = A() 2498b2 = B() 2499)") 2500 .isError()); 2501 2502 Object a1(&scope, mainModuleAt(runtime_, "a1")); 2503 Object b1(&scope, mainModuleAt(runtime_, "b1")); 2504 Object method(&scope, NoneType::object()); 2505 BinaryOpFlags flags; 2506 Object result_obj( 2507 &scope, Interpreter::compareOperationSetMethod(thread_, CompareOp::LE, a1, 2508 b1, &method, &flags)); 2509 EXPECT_TRUE(method.isFunction()); 2510 EXPECT_EQ(flags, kBinaryOpReflected | kBinaryOpNotImplementedRetry); 2511 ASSERT_TRUE(result_obj.isTuple()); 2512 Tuple result(&scope, *result_obj); 2513 ASSERT_EQ(result.length(), 2); 2514 EXPECT_EQ(result.at(0), b1); 2515 EXPECT_EQ(result.at(1), a1); 2516 2517 Object a2(&scope, mainModuleAt(runtime_, "a2")); 2518 Object b2(&scope, mainModuleAt(runtime_, "b2")); 2519 ASSERT_EQ(a1.layoutId(), a2.layoutId()); 2520 ASSERT_EQ(b1.layoutId(), b2.layoutId()); 2521 result_obj = 2522 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *a2, *b2); 2523 ASSERT_TRUE(result_obj.isTuple()); 2524 result = *result_obj; 2525 ASSERT_EQ(result.length(), 2); 2526 EXPECT_EQ(result.at(0), b2); 2527 EXPECT_EQ(result.at(1), a2); 2528} 2529 2530TEST_F(InterpreterTest, 2531 CompareOpSetMethodSetsReverseMethodNotImplementedRetry) { 2532 HandleScope scope(thread_); 2533 ASSERT_FALSE(runFromCStr(runtime_, R"( 2534class A: 2535 def __init__(self, x): 2536 self.x = x 2537 def __le__(self, other): 2538 raise UserWarning("should not be called") 2539class ASub(A): 2540 def __ge__(self, other): 2541 return (self, other) 2542v0 = A(3) 2543v1 = ASub(7) 2544v2 = A(8) 2545v3 = ASub(2) 2546)") 2547 .isError()); 2548 Object v0(&scope, mainModuleAt(runtime_, "v0")); 2549 Object v1(&scope, mainModuleAt(runtime_, "v1")); 2550 Object v2(&scope, mainModuleAt(runtime_, "v2")); 2551 Object v3(&scope, mainModuleAt(runtime_, "v3")); 2552 Object method(&scope, NoneType::object()); 2553 BinaryOpFlags flags; 2554 Object result_obj( 2555 &scope, Interpreter::compareOperationSetMethod(thread_, CompareOp::LE, v0, 2556 v1, &method, &flags)); 2557 EXPECT_TRUE(method.isFunction()); 2558 EXPECT_EQ(flags, kBinaryOpReflected | kBinaryOpNotImplementedRetry); 2559 ASSERT_TRUE(result_obj.isTuple()); 2560 Tuple result(&scope, *result_obj); 2561 ASSERT_EQ(result.length(), 2); 2562 EXPECT_EQ(result.at(0), v1); 2563 EXPECT_EQ(result.at(1), v0); 2564 2565 ASSERT_EQ(v0.layoutId(), v2.layoutId()); 2566 ASSERT_EQ(v1.layoutId(), v3.layoutId()); 2567 result_obj = 2568 Interpreter::binaryOperationWithMethod(thread_, *method, flags, *v2, *v3); 2569 ASSERT_TRUE(result_obj.isTuple()); 2570 result = *result_obj; 2571 ASSERT_EQ(result.length(), 2); 2572 EXPECT_EQ(result.at(0), v3); 2573 EXPECT_EQ(result.at(1), v2); 2574} 2575 2576TEST_F(InterpreterTest, 2577 CompareOpInvokesLeftMethodWhenReflectedMethodReturnsNotImplemented) { 2578 ASSERT_FALSE(runFromCStr(runtime_, R"( 2579trace = "" 2580class C: 2581 def __ge__(self, other): 2582 global trace 2583 trace += "C.__ge__," 2584 return "C.__ge__" 2585 2586 def __le__(self, other): 2587 raise Exception("should not be called") 2588 2589class D(C): 2590 def __ge__(self, other): 2591 raise Exception("should not be called") 2592 2593 def __le__(self, other): 2594 global trace 2595 trace += "D.__le__," 2596 return NotImplemented 2597 2598result = C() >= D() 2599)") 2600 .isError()); 2601 2602 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "C.__ge__")); 2603 EXPECT_TRUE( 2604 isStrEqualsCStr(mainModuleAt(runtime_, "trace"), "D.__le__,C.__ge__,")); 2605} 2606 2607TEST_F( 2608 InterpreterTest, 2609 CompareOpCachedInsertsDependencyForBothOperandsTypesAppropriateAttributes) { 2610 HandleScope scope(thread_); 2611 EXPECT_FALSE(runFromCStr(runtime_, R"( 2612class A: 2613 def __ge__(self, other): 2614 return "from class A" 2615 2616class B: 2617 pass 2618 2619def cache_compare_op(a, b): 2620 return a >= b 2621 2622a = A() 2623b = B() 2624A__ge__ = A.__ge__ 2625result = cache_compare_op(a, b) 2626)") 2627 .isError()); 2628 ASSERT_TRUE( 2629 isStrEqualsCStr(mainModuleAt(runtime_, "result"), "from class A")); 2630 2631 Function cache_compare_op(&scope, mainModuleAt(runtime_, "cache_compare_op")); 2632 MutableTuple caches(&scope, cache_compare_op.caches()); 2633 Object a_obj(&scope, mainModuleAt(runtime_, "a")); 2634 Object b_obj(&scope, mainModuleAt(runtime_, "b")); 2635 BinaryOpFlags flag; 2636 EXPECT_EQ( 2637 icLookupBinaryOp(*caches, 0, a_obj.layoutId(), b_obj.layoutId(), &flag), 2638 mainModuleAt(runtime_, "A__ge__")); 2639 2640 // Verify that A.__ge__ has the dependent. 2641 Type a_type(&scope, mainModuleAt(runtime_, "A")); 2642 Object left_op_name(&scope, runtime_->symbols()->at(ID(__ge__))); 2643 Object a_type_attr(&scope, typeValueCellAt(*a_type, *left_op_name)); 2644 ASSERT_TRUE(a_type_attr.isValueCell()); 2645 ASSERT_TRUE(ValueCell::cast(*a_type_attr).dependencyLink().isWeakLink()); 2646 EXPECT_EQ( 2647 WeakLink::cast(ValueCell::cast(*a_type_attr).dependencyLink()).referent(), 2648 *cache_compare_op); 2649 2650 // Verify that B.__le__ has the dependent. 2651 Type b_type(&scope, mainModuleAt(runtime_, "B")); 2652 Object right_op_name(&scope, runtime_->symbols()->at(ID(__le__))); 2653 Object b_type_attr(&scope, typeValueCellAt(*b_type, *right_op_name)); 2654 ASSERT_TRUE(b_type_attr.isValueCell()); 2655 ASSERT_TRUE(ValueCell::cast(*b_type_attr).dependencyLink().isWeakLink()); 2656 EXPECT_EQ( 2657 WeakLink::cast(ValueCell::cast(*b_type_attr).dependencyLink()).referent(), 2658 *cache_compare_op); 2659} 2660 2661TEST_F(InterpreterTest, DoStoreFastStoresValue) { 2662 HandleScope scope(thread_); 2663 2664 Object obj(&scope, SmallInt::fromWord(1111)); 2665 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 2666 Tuple names(&scope, runtime_->emptyTuple()); 2667 Locals locals; 2668 locals.varcount = 2; 2669 const byte bytecode[] = {LOAD_CONST, 0, 0, 0, STORE_FAST, 1, 0, 0, 2670 LOAD_FAST, 1, 0, 0, RETURN_VALUE, 0, 0, 0}; 2671 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names, 2672 &locals)); 2673 2674 EXPECT_TRUE(isIntEqualsWord(runCodeNoBytecodeRewriting(code), 1111)); 2675} 2676 2677TEST_F(InterpreterTest, DoLoadFastReverseLoadsValue) { 2678 HandleScope scope(thread_); 2679 2680 Object obj1(&scope, SmallInt::fromWord(1)); 2681 Object obj2(&scope, SmallInt::fromWord(22)); 2682 Object obj3(&scope, SmallInt::fromWord(333)); 2683 Object obj4(&scope, SmallInt::fromWord(4444)); 2684 Tuple consts(&scope, runtime_->newTupleWith4(obj1, obj2, obj3, obj4)); 2685 Tuple names(&scope, runtime_->emptyTuple()); 2686 Locals locals; 2687 locals.varcount = 4; 2688 const byte bytecode[] = { 2689 LOAD_CONST, 0, 0, 0, STORE_FAST, 0, 0, 0, 2690 LOAD_CONST, 1, 0, 0, STORE_FAST, 1, 0, 0, 2691 LOAD_CONST, 2, 0, 0, STORE_FAST, 2, 0, 0, 2692 LOAD_CONST, 3, 0, 0, STORE_FAST, 3, 0, 0, 2693 LOAD_FAST_REVERSE, 3, 0, 0, // 1 2694 LOAD_FAST_REVERSE, 2, 0, 0, // 22 2695 LOAD_FAST_REVERSE, 0, 0, 0, // 4444 2696 LOAD_FAST_REVERSE, 1, 0, 0, // 333 2697 BUILD_TUPLE, 4, 0, 0, RETURN_VALUE, 0, 0, 0, 2698 }; 2699 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names, 2700 &locals)); 2701 2702 Object result_obj(&scope, runCodeNoBytecodeRewriting(code)); 2703 ASSERT_TRUE(result_obj.isTuple()); 2704 Tuple result(&scope, *result_obj); 2705 ASSERT_EQ(result.length(), 4); 2706 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1)); 2707 EXPECT_TRUE(isIntEqualsWord(result.at(1), 22)); 2708 EXPECT_TRUE(isIntEqualsWord(result.at(2), 4444)); 2709 EXPECT_TRUE(isIntEqualsWord(result.at(3), 333)); 2710} 2711 2712TEST_F(InterpreterTest, 2713 DoLoadFastReverseFromUninitializedLocalRaisesUnboundLocalError) { 2714 HandleScope scope(thread_); 2715 2716 Object obj(&scope, SmallInt::fromWord(42)); 2717 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 2718 Tuple names(&scope, runtime_->emptyTuple()); 2719 Locals locals; 2720 locals.varcount = 3; 2721 const byte bytecode[] = { 2722 LOAD_CONST, 0, 0, 0, STORE_FAST, 0, 0, 0, LOAD_CONST, 0, 0, 0, 2723 STORE_FAST, 2, 0, 0, DELETE_FAST, 2, 0, 0, LOAD_FAST_REVERSE, 0, 0, 0, 2724 RETURN_VALUE, 0, 0, 0, 2725 }; 2726 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names, 2727 &locals)); 2728 2729 EXPECT_TRUE(raisedWithStr( 2730 runCodeNoBytecodeRewriting(code), LayoutId::kUnboundLocalError, 2731 "local variable 'var2' referenced before assignment")); 2732} 2733 2734TEST_F(InterpreterTest, DoStoreFastReverseStoresValue) { 2735 HandleScope scope(thread_); 2736 2737 Object obj1(&scope, SmallInt::fromWord(1)); 2738 Object obj2(&scope, SmallInt::fromWord(22)); 2739 Object obj3(&scope, SmallInt::fromWord(333)); 2740 Object obj4(&scope, SmallInt::fromWord(4444)); 2741 Tuple consts(&scope, runtime_->newTupleWith4(obj1, obj2, obj3, obj4)); 2742 Tuple names(&scope, runtime_->emptyTuple()); 2743 Locals locals; 2744 locals.varcount = 4; 2745 const byte bytecode[] = { 2746 LOAD_CONST, 0, 0, 0, STORE_FAST_REVERSE, 0, 0, 0, 2747 LOAD_CONST, 1, 0, 0, STORE_FAST_REVERSE, 1, 0, 0, 2748 LOAD_CONST, 2, 0, 0, STORE_FAST_REVERSE, 3, 0, 0, 2749 LOAD_CONST, 3, 0, 0, STORE_FAST_REVERSE, 2, 0, 0, 2750 LOAD_FAST, 0, 0, 0, // 333 2751 LOAD_FAST, 1, 0, 0, // 4444 2752 LOAD_FAST, 2, 0, 0, // 22 2753 LOAD_FAST, 3, 0, 0, // 1 2754 BUILD_TUPLE, 4, 0, 0, RETURN_VALUE, 0, 0, 0, 2755 }; 2756 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names, 2757 &locals)); 2758 2759 Object result_obj(&scope, runCodeNoBytecodeRewriting(code)); 2760 ASSERT_TRUE(result_obj.isTuple()); 2761 Tuple result(&scope, *result_obj); 2762 ASSERT_EQ(result.length(), 4); 2763 EXPECT_TRUE(isIntEqualsWord(result.at(0), 333)); 2764 EXPECT_TRUE(isIntEqualsWord(result.at(1), 4444)); 2765 EXPECT_TRUE(isIntEqualsWord(result.at(2), 22)); 2766 EXPECT_TRUE(isIntEqualsWord(result.at(3), 1)); 2767} 2768 2769TEST_F(InterpreterTest, DoStoreSubscrWithNoSetitemRaisesTypeError) { 2770 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "1[5] = 'foo'"), 2771 LayoutId::kTypeError, 2772 "'int' object does not support item assignment")); 2773} 2774 2775TEST_F(InterpreterTest, DoStoreSubscrWithDescriptorPropagatesException) { 2776 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 2777class A: 2778 def __get__(self, *args): 2779 raise RuntimeError("foo") 2780 2781class B: 2782 __setitem__ = A() 2783 2784b = B() 2785b[5] = 'foo' 2786)"), 2787 LayoutId::kRuntimeError, "foo")); 2788} 2789 2790TEST_F(InterpreterTest, DoDeleteSubscrWithNoDelitemRaisesTypeError) { 2791 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "del 1[5]"), 2792 LayoutId::kTypeError, 2793 "'int' object does not support item deletion")); 2794} 2795 2796TEST_F(InterpreterTest, DoDeleteSubscrWithDescriptorPropagatesException) { 2797 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 2798class A: 2799 def __get__(self, *args): 2800 raise RuntimeError("foo") 2801 2802class B: 2803 __delitem__ = A() 2804 2805b = B() 2806del b[5] 2807)"), 2808 LayoutId::kRuntimeError, "foo")); 2809} 2810 2811TEST_F(InterpreterTest, DoDeleteSubscrDoesntPushToStack) { 2812 HandleScope scope(thread_); 2813 2814 List list(&scope, runtime_->newList()); 2815 Int one(&scope, runtime_->newInt(1)); 2816 runtime_->listEnsureCapacity(thread_, list, 1); 2817 list.setNumItems(1); 2818 list.atPut(0, *one); 2819 Object obj1(&scope, SmallInt::fromWord(42)); 2820 Object obj3(&scope, SmallInt::fromWord(0)); 2821 Tuple consts(&scope, runtime_->newTupleWith3(obj1, list, obj3)); 2822 const byte bytecode[] = { 2823 LOAD_CONST, 0, LOAD_CONST, 1, LOAD_CONST, 2, 2824 DELETE_SUBSCR, 0, RETURN_VALUE, 0, 2825 }; 2826 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2827 2828 Object result_obj(&scope, runCode(code)); 2829 ASSERT_TRUE(result_obj.isInt()); 2830 Int result(&scope, *result_obj); 2831 EXPECT_EQ(result.asWord(), 42); 2832 EXPECT_EQ(list.numItems(), 0); 2833} 2834 2835TEST_F(InterpreterTest, GetIterWithSequenceReturnsIterator) { 2836 ASSERT_FALSE(runFromCStr(runtime_, R"( 2837class Sequence: 2838 def __getitem__(s, i): 2839 return ("foo", "bar")[i] 2840 2841seq = Sequence() 2842)") 2843 .isError()); 2844 HandleScope scope(thread_); 2845 2846 Object obj(&scope, mainModuleAt(runtime_, "seq")); 2847 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 2848 const byte bytecode[] = { 2849 LOAD_CONST, 0, GET_ITER, 0, RETURN_VALUE, 0, 2850 }; 2851 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 2852 2853 Object result_obj(&scope, runCode(code)); 2854 EXPECT_TRUE(runtime_->isIterator(thread_, result_obj)); 2855 Type result_type(&scope, runtime_->typeOf(*result_obj)); 2856 EXPECT_TRUE(isStrEqualsCStr(result_type.name(), "iterator")); 2857} 2858 2859TEST_F(InterpreterTest, 2860 GetIterWithRaisingDescriptorDunderIterPropagatesException) { 2861 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 2862class Desc: 2863 def __get__(self, obj, type): 2864 raise UserWarning("foo") 2865 2866class C: 2867 __iter__ = Desc() 2868 2869it = C() 2870result = [x for x in it] 2871)"), 2872 LayoutId::kTypeError, 2873 "'C' object is not iterable")); 2874} 2875 2876TEST_F(InterpreterTest, SequenceContains) { 2877 HandleScope scope(thread_); 2878 2879 ASSERT_FALSE(runFromCStr(runtime_, R"( 2880a = {1, 2} 2881 2882b = 1 2883c = 3 2884)") 2885 .isError()); 2886 2887 Object container(&scope, mainModuleAt(runtime_, "a")); 2888 Object b(&scope, mainModuleAt(runtime_, "b")); 2889 Object c(&scope, mainModuleAt(runtime_, "c")); 2890 Object contains_true(&scope, 2891 Interpreter::sequenceContains(thread_, b, container)); 2892 Object contains_false(&scope, 2893 Interpreter::sequenceContains(thread_, c, container)); 2894 EXPECT_EQ(contains_true, Bool::trueObj()); 2895 EXPECT_EQ(contains_false, Bool::falseObj()); 2896} 2897 2898TEST_F(InterpreterTest, SequenceIterSearchWithNoDunderIterRaisesTypeError) { 2899 HandleScope scope(thread_); 2900 ASSERT_FALSE(runFromCStr(runtime_, R"( 2901class C: pass 2902container = C() 2903)") 2904 .isError()); 2905 Object container(&scope, mainModuleAt(runtime_, "container")); 2906 Object val(&scope, NoneType::object()); 2907 Object result(&scope, 2908 Interpreter::sequenceIterSearch(thread_, val, container)); 2909 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 2910} 2911 2912TEST_F(InterpreterTest, 2913 SequenceIterSearchWithNonCallableDunderIterRaisesTypeError) { 2914 HandleScope scope(thread_); 2915 ASSERT_FALSE(runFromCStr(runtime_, R"( 2916class C: 2917 __iter__ = None 2918container = C() 2919)") 2920 .isError()); 2921 Object container(&scope, mainModuleAt(runtime_, "container")); 2922 Object val(&scope, NoneType::object()); 2923 Object result(&scope, 2924 Interpreter::sequenceIterSearch(thread_, val, container)); 2925 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 2926} 2927 2928TEST_F(InterpreterTest, SequenceIterSearchWithNoDunderNextRaisesTypeError) { 2929 HandleScope scope(thread_); 2930 ASSERT_FALSE(runFromCStr(runtime_, R"( 2931class D: pass 2932class C: 2933 def __iter__(self): 2934 return D() 2935container = C() 2936)") 2937 .isError()); 2938 Object container(&scope, mainModuleAt(runtime_, "container")); 2939 Object val(&scope, NoneType::object()); 2940 Object result(&scope, 2941 Interpreter::sequenceIterSearch(thread_, val, container)); 2942 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 2943} 2944 2945TEST_F(InterpreterTest, 2946 SequenceIterSearchWithNonCallableDunderNextRaisesTypeError) { 2947 HandleScope scope(thread_); 2948 ASSERT_FALSE(runFromCStr(runtime_, R"( 2949class D: 2950 __next__ = None 2951class C: 2952 def __iter__(self): 2953 return D() 2954container = C() 2955)") 2956 .isError()); 2957 Object container(&scope, mainModuleAt(runtime_, "container")); 2958 Object val(&scope, NoneType::object()); 2959 Object result(&scope, 2960 Interpreter::sequenceIterSearch(thread_, val, container)); 2961 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 2962} 2963 2964TEST_F(InterpreterTest, SequenceIterSearchWithListReturnsTrue) { 2965 HandleScope scope(thread_); 2966 List container(&scope, listFromRange(1, 3)); 2967 Object val(&scope, SmallInt::fromWord(2)); 2968 Object result(&scope, 2969 Interpreter::sequenceIterSearch(thread_, val, container)); 2970 ASSERT_FALSE(result.isError()); 2971 EXPECT_EQ(result, Bool::trueObj()); 2972} 2973 2974TEST_F(InterpreterTest, SequenceIterSearchWithListReturnsFalse) { 2975 HandleScope scope(thread_); 2976 Object container(&scope, listFromRange(1, 3)); 2977 Object val(&scope, SmallInt::fromWord(5)); 2978 Object result(&scope, 2979 Interpreter::sequenceIterSearch(thread_, val, container)); 2980 ASSERT_FALSE(result.isError()); 2981 EXPECT_EQ(result, Bool::falseObj()); 2982} 2983 2984TEST_F(InterpreterTest, SequenceIterSearchWithSequenceSearchesIterator) { 2985 HandleScope scope(thread_); 2986 ASSERT_FALSE(runFromCStr(runtime_, R"( 2987class Seq: 2988 def __getitem__(s, i): 2989 return ("foo", "bar", 42)[i] 2990 2991seq_iter = Seq() 2992)") 2993 .isError()); 2994 Object seq_iter(&scope, mainModuleAt(runtime_, "seq_iter")); 2995 Object obj_in_seq(&scope, SmallInt::fromWord(42)); 2996 Object contains_true( 2997 &scope, Interpreter::sequenceIterSearch(thread_, obj_in_seq, seq_iter)); 2998 EXPECT_EQ(contains_true, Bool::trueObj()); 2999 Object obj_not_in_seq(&scope, NoneType::object()); 3000 Object contains_false(&scope, Interpreter::sequenceIterSearch( 3001 thread_, obj_not_in_seq, seq_iter)); 3002 EXPECT_EQ(contains_false, Bool::falseObj()); 3003} 3004 3005TEST_F(InterpreterTest, 3006 SequenceIterSearchWithIterThatRaisesPropagatesException) { 3007 HandleScope scope(thread_); 3008 ASSERT_FALSE(runFromCStr(runtime_, R"( 3009class C: 3010 def __iter__(self): 3011 raise ZeroDivisionError("boom") 3012container = C() 3013)") 3014 .isError()); 3015 Object container(&scope, mainModuleAt(runtime_, "container")); 3016 Object val(&scope, SmallInt::fromWord(5)); 3017 Object result(&scope, 3018 Interpreter::sequenceIterSearch(thread_, val, container)); 3019 EXPECT_TRUE(raised(*result, LayoutId::kZeroDivisionError)); 3020} 3021 3022TEST_F(InterpreterTest, ContextManagerCallEnterExit) { 3023 const char* src = R"( 3024a = 1 3025class Foo: 3026 def __enter__(self): 3027 global a 3028 a = 2 3029 3030 def __exit__(self, e, t, b): 3031 global a 3032 a = 3 3033 3034b = 0 3035with Foo(): 3036 b = a 3037 3038)"; 3039 HandleScope scope(thread_); 3040 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 3041 Object a(&scope, mainModuleAt(runtime_, "a")); 3042 EXPECT_TRUE(isIntEqualsWord(*a, 3)); 3043 Object b(&scope, mainModuleAt(runtime_, "b")); 3044 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 3045} 3046 3047TEST_F(InterpreterTest, ContextManagerCallEnterExitOfNotFunctionType) { 3048 const char* src = R"( 3049class MyFunction: 3050 def __init__(self, fn): 3051 self.fn = fn 3052 3053 def __get__(self, instance, instance_type): 3054 return self.fn 3055 3056a = 1 3057 3058def my_enter(): 3059 global a 3060 a = 2 3061 3062def my_exit(e, t, b): 3063 global a 3064 a = 3 3065 3066class Foo: 3067 __enter__ = MyFunction(my_enter) 3068 __exit__ = MyFunction(my_exit) 3069 3070b = 0 3071with Foo(): 3072 b = a 3073)"; 3074 HandleScope scope(thread_); 3075 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 3076 Object a(&scope, mainModuleAt(runtime_, "a")); 3077 EXPECT_TRUE(isIntEqualsWord(*a, 3)); 3078 Object b(&scope, mainModuleAt(runtime_, "b")); 3079 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 3080} 3081 3082TEST_F(InterpreterTest, StackCleanupAfterCallFunction) { 3083 // Build the following function 3084 // def foo(arg0=1, arg1=2): 3085 // return 42 3086 // 3087 // Then call as foo(1) and verify that the stack is cleaned up after 3088 // default argument expansion 3089 // 3090 HandleScope scope(thread_); 3091 3092 Object obj(&scope, SmallInt::fromWord(42)); 3093 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 3094 Tuple names(&scope, runtime_->emptyTuple()); 3095 Locals locals; 3096 locals.argcount = 2; 3097 const byte bytecode[] = {LOAD_CONST, 0, RETURN_VALUE, 0}; 3098 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names, 3099 &locals)); 3100 3101 Object qualname(&scope, Str::empty()); 3102 Module module(&scope, findMainModule(runtime_)); 3103 Function callee( 3104 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 3105 3106 Object obj1(&scope, SmallInt::fromWord(1)); 3107 Object obj2(&scope, SmallInt::fromWord(2)); 3108 Tuple defaults(&scope, runtime_->newTupleWith2(obj1, obj2)); 3109 callee.setDefaults(*defaults); 3110 3111 // Save starting value stack top 3112 RawObject* value_stack_start = thread_->stackPointer(); 3113 3114 // Push function pointer and argument 3115 thread_->stackPush(*callee); 3116 thread_->stackPush(SmallInt::fromWord(1)); 3117 3118 // Make sure we got the right result and stack is back where it should be 3119 EXPECT_TRUE(isIntEqualsWord(Interpreter::call(thread_, 1), 42)); 3120 EXPECT_EQ(value_stack_start, thread_->stackPointer()); 3121} 3122 3123TEST_F(InterpreterTest, StackCleanupAfterCallExFunction) { 3124 // Build the following function 3125 // def foo(arg0=1, arg1=2): 3126 // return 42 3127 // 3128 // Then call as "f=(2,); foo(*f)" and verify that the stack is cleaned up 3129 // after ex and default argument expansion 3130 // 3131 HandleScope scope(thread_); 3132 3133 Object obj(&scope, SmallInt::fromWord(42)); 3134 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 3135 Tuple names(&scope, runtime_->emptyTuple()); 3136 Locals locals; 3137 locals.argcount = 2; 3138 const byte bytecode[] = {LOAD_CONST, 0, RETURN_VALUE, 0}; 3139 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names, 3140 &locals)); 3141 3142 Object qualname(&scope, Str::empty()); 3143 Module module(&scope, findMainModule(runtime_)); 3144 Function callee( 3145 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 3146 3147 Object obj1(&scope, SmallInt::fromWord(1)); 3148 Object obj2(&scope, SmallInt::fromWord(2)); 3149 Tuple defaults(&scope, runtime_->newTupleWith2(obj1, obj2)); 3150 callee.setDefaults(*defaults); 3151 3152 // Save starting value stack top 3153 RawObject* value_stack_start = thread_->stackPointer(); 3154 3155 // Push function pointer and argument 3156 Object arg(&scope, SmallInt::fromWord(2)); 3157 Tuple ex(&scope, runtime_->newTupleWith1(arg)); 3158 thread_->stackPush(*callee); 3159 thread_->stackPush(*ex); 3160 3161 // Make sure we got the right result and stack is back where it should be 3162 EXPECT_TRUE(isIntEqualsWord(Interpreter::callEx(thread_, 0), 42)); 3163 EXPECT_EQ(value_stack_start, thread_->stackPointer()); 3164} 3165 3166TEST_F(InterpreterTest, StackCleanupAfterCallKwFunction) { 3167 HandleScope scope(thread_); 3168 3169 // Build the following function 3170 // def foo(arg0=1, arg1=2): 3171 // return 42 3172 // 3173 // Then call as "foo(b=4)" and verify that the stack is cleaned up after 3174 // ex and default argument expansion 3175 // 3176 3177 Object obj(&scope, SmallInt::fromWord(42)); 3178 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 3179 Tuple names(&scope, runtime_->emptyTuple()); 3180 Locals locals; 3181 locals.argcount = 2; 3182 const byte bytecode[] = {LOAD_CONST, 0, RETURN_VALUE, 0}; 3183 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names, 3184 &locals)); 3185 3186 Object qualname(&scope, Str::empty()); 3187 Module module(&scope, findMainModule(runtime_)); 3188 Function callee( 3189 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 3190 Object default1(&scope, SmallInt::fromWord(1)); 3191 Object default2(&scope, SmallInt::fromWord(2)); 3192 Tuple defaults(&scope, runtime_->newTupleWith2(default1, default2)); 3193 callee.setDefaults(*defaults); 3194 3195 // Save starting value stack top 3196 RawObject* value_stack_start = thread_->stackPointer(); 3197 3198 // Push function pointer and argument 3199 Object arg(&scope, Runtime::internStrFromCStr(thread_, "arg1")); 3200 Tuple arg_names(&scope, runtime_->newTupleWith1(arg)); 3201 thread_->stackPush(*callee); 3202 thread_->stackPush(SmallInt::fromWord(4)); 3203 thread_->stackPush(*arg_names); 3204 3205 // Make sure we got the right result and stack is back where it should be 3206 EXPECT_TRUE(isIntEqualsWord(Interpreter::callKw(thread_, 1), 42)); 3207 EXPECT_EQ(value_stack_start, thread_->stackPointer()); 3208} 3209 3210TEST_F(InterpreterTest, LookupMethodInvokesDescriptor) { 3211 HandleScope scope(thread_); 3212 ASSERT_FALSE(runFromCStr(runtime_, R"( 3213def f(): pass 3214 3215class D: 3216 def __get__(self, obj, owner): 3217 return f 3218 3219class C: 3220 __call__ = D() 3221 3222c = C() 3223 )") 3224 .isError()); 3225 Object c(&scope, mainModuleAt(runtime_, "c")); 3226 Object f(&scope, mainModuleAt(runtime_, "f")); 3227 Object method(&scope, Interpreter::lookupMethod(thread_, c, ID(__call__))); 3228 EXPECT_EQ(*f, *method); 3229} 3230 3231TEST_F(InterpreterTest, PrepareCallableCallUnpacksBoundMethod) { 3232 HandleScope scope(thread_); 3233 ASSERT_FALSE(runFromCStr(runtime_, R"( 3234class C: 3235 def foo(): 3236 pass 3237meth = C().foo 3238)") 3239 .isError()); 3240 Object meth_obj(&scope, mainModuleAt(runtime_, "meth")); 3241 ASSERT_TRUE(meth_obj.isBoundMethod()); 3242 3243 thread_->stackPush(*meth_obj); 3244 thread_->stackPush(SmallInt::fromWord(1234)); 3245 ASSERT_EQ(thread_->valueStackSize(), 2); 3246 word nargs = 1; 3247 Interpreter::PrepareCallableResult result = 3248 Interpreter::prepareCallableCall(thread_, nargs, nargs); 3249 ASSERT_TRUE(result.function.isFunction()); 3250 ASSERT_EQ(result.nargs, 2); 3251 ASSERT_EQ(thread_->valueStackSize(), 3); 3252 EXPECT_TRUE(isIntEqualsWord(thread_->stackPeek(0), 1234)); 3253 EXPECT_TRUE(thread_->stackPeek(1).isInstance()); 3254 EXPECT_EQ(thread_->stackPeek(2), result.function); 3255} 3256 3257TEST_F(InterpreterTest, CallExWithListSubclassCallsDunderIter) { 3258 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 3259class C(list): 3260 def __iter__(self): 3261 raise UserWarning('foo') 3262 3263def f(a, b, c): 3264 return (a, b, c) 3265 3266c = C([1, 2, 3]) 3267f(*c) 3268)"), 3269 LayoutId::kUserWarning, "foo")); 3270} 3271 3272static RawObject ALIGN_16 setPendingSignal(Thread* thread, Arguments) { 3273 thread->runtime()->setPendingSignal(thread, SIGINT); 3274 return NoneType::object(); 3275} 3276 3277TEST_F(InterpreterTest, CallFunctionWithInterruptSetReturnsErrorException) { 3278 addBuiltin("set_pending_signal", setPendingSignal, {nullptr, 0}, 0); 3279 EXPECT_FALSE(runFromCStr(runtime_, R"( 3280executed = False 3281def foo(): 3282 global executed 3283 executed = True 3284 3285def bar(): 3286 set_pending_signal() 3287 foo() 3288)") 3289 .isError()); 3290 HandleScope scope(thread_); 3291 Object bar(&scope, mainModuleAt(runtime_, "bar")); 3292 thread_->stackPush(*bar); 3293 EXPECT_TRUE( 3294 raised(Interpreter::call0(thread_, bar), LayoutId::kKeyboardInterrupt)); 3295 Object executed(&scope, mainModuleAt(runtime_, "executed")); 3296 EXPECT_EQ(executed, Bool::falseObj()); 3297} 3298 3299static RawObject ALIGN_16 abortBuiltin(Thread*, Arguments) { abort(); } 3300 3301TEST_F(InterpreterTest, CallFunctionWithBuiltinRaisesRecursionError) { 3302 addBuiltin("abort", abortBuiltin, {nullptr, 0}, 0); 3303 EXPECT_FALSE(runFromCStr(runtime_, R"( 3304x = None 3305def foo(): 3306 global x 3307 x = 1 3308 abort() 3309 x = 2 3310)") 3311 .isError()); 3312 3313 HandleScope scope(thread_); 3314 Object foo(&scope, mainModuleAt(runtime_, "foo")); 3315 3316 // Fill stack until we can fit exactly 1 function call. 3317 RawObject* saved_sp = thread_->stackPointer(); 3318 while (!thread_->wouldStackOverflow(Frame::kSize * 2)) { 3319 thread_->stackPush(NoneType::object()); 3320 } 3321 EXPECT_TRUE( 3322 raised(Interpreter::call0(thread_, foo), LayoutId::kRecursionError)); 3323 Object x(&scope, mainModuleAt(runtime_, "x")); 3324 EXPECT_TRUE(isIntEqualsWord(*x, 1)); 3325 thread_->setStackPointer(saved_sp); 3326} 3327 3328TEST_F(InterpreterTest, CallingUncallableRaisesTypeError) { 3329 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "(1)()"), 3330 LayoutId::kTypeError, 3331 "'int' object is not callable")); 3332} 3333 3334TEST_F(InterpreterTest, CallingUncallableDunderCallRaisesTypeError) { 3335 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 3336class C: 3337 __call__ = 1 3338 3339c = C() 3340c() 3341 )"), 3342 LayoutId::kTypeError, 3343 "'int' object is not callable")); 3344} 3345 3346TEST_F(InterpreterTest, 3347 CallingBoundMethodWithNonFunctionDunderFuncCallsDunderFunc) { 3348 EXPECT_FALSE(runFromCStr(runtime_, R"( 3349# from types import MethodType 3350MethodType = method 3351 3352class C: 3353 def __call__(self, arg): 3354 return self, arg 3355 3356func = C() 3357instance = object() 3358bound_method = MethodType(func, instance) 3359result = bound_method() 3360 )") 3361 .isError()); 3362 CHECK(!thread_->hasPendingException(), "no errors pls"); 3363 HandleScope scope(thread_); 3364 Object result_obj(&scope, mainModuleAt(runtime_, "result")); 3365 ASSERT_TRUE(result_obj.isTuple()); 3366 Tuple result(&scope, *result_obj); 3367 ASSERT_EQ(result.length(), 2); 3368 Object func(&scope, mainModuleAt(runtime_, "func")); 3369 EXPECT_EQ(result.at(0), *func); 3370 Object instance(&scope, mainModuleAt(runtime_, "instance")); 3371 EXPECT_EQ(result.at(1), *instance); 3372} 3373 3374TEST_F(InterpreterTest, CallingNonDescriptorDunderCallRaisesTypeError) { 3375 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 3376class D: pass 3377 3378class C: 3379 __call__ = D() 3380 3381c = C() 3382c() 3383 )"), 3384 LayoutId::kTypeError, 3385 "'D' object is not callable")); 3386} 3387 3388TEST_F(InterpreterTest, CallDescriptorReturningUncallableRaisesTypeError) { 3389 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 3390class D: 3391 def __get__(self, instance, owner): 3392 return 1 3393 3394class C: 3395 __call__ = D() 3396 3397c = C() 3398c() 3399 )"), 3400 LayoutId::kTypeError, 3401 "'int' object is not callable")); 3402} 3403 3404TEST_F(InterpreterTest, LookupMethodLoopsOnCallBoundToDescriptor) { 3405 HandleScope scope(thread_); 3406 ASSERT_FALSE(runFromCStr(runtime_, R"( 3407def f(args): 3408 return args 3409 3410class C0: 3411 def __get__(self, obj, owner): 3412 return f 3413 3414class C1: 3415 __call__ = C0() 3416 3417class C2: 3418 def __get__(self, obj, owner): 3419 return C1() 3420 3421class C3: 3422 __call__ = C2() 3423 3424c = C3() 3425result = c(42) 3426 )") 3427 .isError()); 3428 Object result(&scope, mainModuleAt(runtime_, "result")); 3429 EXPECT_EQ(*result, SmallInt::fromWord(42)); 3430} 3431 3432TEST_F(InterpreterTest, DunderIterReturnsNonIterable) { 3433 const char* src = R"( 3434class Foo: 3435 def __iter__(self): 3436 return 1 3437a, b = Foo() 3438)"; 3439 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError, 3440 "iter() returned non-iterator of type 'int'")); 3441} 3442 3443TEST_F(InterpreterTest, UnpackSequence) { 3444 HandleScope scope(thread_); 3445 ASSERT_FALSE(runFromCStr(runtime_, R"( 3446l = [1, 2, 3] 3447a, b, c = l 3448)") 3449 .isError()); 3450 Object a(&scope, mainModuleAt(runtime_, "a")); 3451 Object b(&scope, mainModuleAt(runtime_, "b")); 3452 Object c(&scope, mainModuleAt(runtime_, "c")); 3453 EXPECT_TRUE(isIntEqualsWord(*a, 1)); 3454 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 3455 EXPECT_TRUE(isIntEqualsWord(*c, 3)); 3456} 3457 3458TEST_F(InterpreterTest, UnpackSequenceWithSeqIterator) { 3459 HandleScope scope(thread_); 3460 ASSERT_FALSE(runFromCStr(runtime_, R"( 3461class Seq: 3462 def __getitem__(s, i): 3463 return ("foo", "bar", 42)[i] 3464a, b, c = Seq() 3465)") 3466 .isError()); 3467 Object a(&scope, mainModuleAt(runtime_, "a")); 3468 Object b(&scope, mainModuleAt(runtime_, "b")); 3469 Object c(&scope, mainModuleAt(runtime_, "c")); 3470 EXPECT_TRUE(isStrEqualsCStr(*a, "foo")); 3471 EXPECT_TRUE(isStrEqualsCStr(*b, "bar")); 3472 EXPECT_TRUE(isIntEqualsWord(*c, 42)); 3473} 3474 3475TEST_F(InterpreterTest, UnpackSequenceTooFewObjects) { 3476 const char* src = R"( 3477l = [1, 2] 3478a, b, c = l 3479)"; 3480 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kValueError, 3481 "not enough values to unpack")); 3482} 3483 3484TEST_F(InterpreterTest, UnpackSequenceTooManyObjects) { 3485 const char* src = R"( 3486l = [1, 2, 3, 4] 3487a, b, c = l 3488)"; 3489 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kValueError, 3490 "too many values to unpack")); 3491} 3492 3493TEST_F(InterpreterTest, UnpackTuple) { 3494 HandleScope scope(thread_); 3495 ASSERT_FALSE(runFromCStr(runtime_, R"( 3496l = (1, 2, 3) 3497a, b, c = l 3498)") 3499 .isError()); 3500 Object a(&scope, mainModuleAt(runtime_, "a")); 3501 Object b(&scope, mainModuleAt(runtime_, "b")); 3502 Object c(&scope, mainModuleAt(runtime_, "c")); 3503 EXPECT_TRUE(isIntEqualsWord(*a, 1)); 3504 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 3505 EXPECT_TRUE(isIntEqualsWord(*c, 3)); 3506} 3507 3508TEST_F(InterpreterTest, UnpackTupleTooFewObjects) { 3509 const char* src = R"( 3510l = (1, 2) 3511a, b, c = l 3512)"; 3513 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kValueError, 3514 "not enough values to unpack")); 3515} 3516 3517TEST_F(InterpreterTest, UnpackTupleTooManyObjects) { 3518 const char* src = R"( 3519l = (1, 2, 3, 4) 3520a, b, c = l 3521)"; 3522 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kValueError, 3523 "too many values to unpack")); 3524} 3525 3526TEST_F(InterpreterTest, UnpackSequenceWithStructseq) { 3527 ASSERT_FALSE(runFromCStr(runtime_, R"( 3528from _builtins import _structseq_new_type 3529C = _structseq_new_type("C", ("a", "b", "c")) 3530obj = C((1,2,3)) 3531a, b, c = obj 3532)") 3533 .isError()); 3534 HandleScope scope(thread_); 3535 Object a(&scope, mainModuleAt(runtime_, "a")); 3536 Object b(&scope, mainModuleAt(runtime_, "b")); 3537 Object c(&scope, mainModuleAt(runtime_, "c")); 3538 EXPECT_TRUE(isIntEqualsWord(*a, 1)); 3539 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 3540 EXPECT_TRUE(isIntEqualsWord(*c, 3)); 3541} 3542 3543TEST_F(InterpreterTest, UnpackSequenceWithStructseqTooFewObjects) { 3544 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 3545from _builtins import _structseq_new_type 3546C = _structseq_new_type("C", ("a", "b")) 3547obj = C((1,2)) 3548a, b, c = obj 3549)"), 3550 LayoutId::kValueError, 3551 "not enough values to unpack")); 3552} 3553 3554TEST_F(InterpreterTest, UnpackSequenceWithStructseqTooManyObjects) { 3555 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 3556from _builtins import _structseq_new_type 3557C = _structseq_new_type("C", ("a", "b", "c")) 3558obj = C((1,2,3)) 3559a, b = obj 3560)"), 3561 LayoutId::kValueError, 3562 "too many values to unpack")); 3563} 3564 3565TEST_F(InterpreterTest, UnpackSequenceWithStructseqInObj) { 3566 ASSERT_FALSE(runFromCStr(runtime_, R"( 3567from _builtins import _structseq_new_type 3568C = _structseq_new_type("C", ("a", "b", "c"), num_in_sequence=2) 3569obj = C((1,2,3)) 3570a, b = obj 3571)") 3572 .isError()); 3573 HandleScope scope(thread_); 3574 Object a(&scope, mainModuleAt(runtime_, "a")); 3575 Object b(&scope, mainModuleAt(runtime_, "b")); 3576 EXPECT_TRUE(isIntEqualsWord(*a, 1)); 3577 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 3578} 3579 3580TEST_F(InterpreterTest, UnpackSequenceWithStructseqTooFewObjectsInSeq) { 3581 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 3582from _builtins import _structseq_new_type 3583C = _structseq_new_type("C", ("a", "b", "c"), num_in_sequence=2) 3584obj = C((1,2,3)) 3585a, b, c = obj 3586)"), 3587 LayoutId::kValueError, 3588 "not enough values to unpack")); 3589} 3590 3591TEST_F(InterpreterTest, UnpackSequenceWithStructseqTooManyObjectsInSeq) { 3592 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 3593from _builtins import _structseq_new_type 3594C = _structseq_new_type("C", ("a", "b", "c", "d"), num_in_sequence=3) 3595obj = C((1,2,3,4)) 3596a, b = obj 3597)"), 3598 LayoutId::kValueError, 3599 "too many values to unpack")); 3600} 3601 3602TEST_F(InterpreterTest, PrintExprInvokesDisplayhook) { 3603 HandleScope scope(thread_); 3604 ASSERT_FALSE(runFromCStr(runtime_, R"( 3605import sys 3606 3607MY_GLOBAL = 1234 3608 3609def my_displayhook(value): 3610 global MY_GLOBAL 3611 MY_GLOBAL = value 3612 3613sys.displayhook = my_displayhook 3614 )") 3615 .isError()); 3616 3617 Object unique(&scope, runtime_->newList()); // unique object 3618 3619 Object none(&scope, NoneType::object()); 3620 Tuple consts(&scope, runtime_->newTupleWith2(unique, none)); 3621 const byte bytecode[] = {LOAD_CONST, 0, PRINT_EXPR, 0, 3622 LOAD_CONST, 1, RETURN_VALUE, 0}; 3623 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3624 3625 ASSERT_TRUE(runCode(code).isNoneType()); 3626 3627 Object displayhook(&scope, moduleAtByCStr(runtime_, "sys", "displayhook")); 3628 Object my_displayhook(&scope, mainModuleAt(runtime_, "my_displayhook")); 3629 EXPECT_EQ(*displayhook, *my_displayhook); 3630 3631 Object my_global(&scope, mainModuleAt(runtime_, "MY_GLOBAL")); 3632 EXPECT_EQ(*my_global, *unique); 3633} 3634 3635TEST_F(InterpreterTest, PrintExprtDoesntPushToStack) { 3636 HandleScope scope(thread_); 3637 ASSERT_FALSE(runFromCStr(runtime_, R"( 3638import sys 3639 3640def my_displayhook(value): 3641 pass 3642 3643sys.displayhook = my_displayhook 3644 )") 3645 .isError()); 3646 3647 Object obj1(&scope, SmallInt::fromWord(42)); 3648 Object obj2(&scope, SmallInt::fromWord(0)); 3649 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2)); 3650 // This bytecode loads 42 onto the stack, along with a value to print. 3651 // It then returns the top of the stack, which should be 42. 3652 const byte bytecode[] = { 3653 LOAD_CONST, 0, LOAD_CONST, 1, PRINT_EXPR, 0, RETURN_VALUE, 0, 3654 }; 3655 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3656 3657 Object result_obj(&scope, runCode(code)); 3658 EXPECT_TRUE(isIntEqualsWord(*result_obj, 42)); 3659} 3660 3661TEST_F(InterpreterTest, GetAiterCallsAiter) { 3662 HandleScope scope(thread_); 3663 ASSERT_FALSE(runFromCStr(runtime_, R"( 3664class AsyncIterable: 3665 def __aiter__(self): 3666 return 42 3667 3668a = AsyncIterable() 3669)") 3670 .isError()); 3671 3672 Object a(&scope, mainModuleAt(runtime_, "a")); 3673 3674 Tuple consts(&scope, runtime_->newTupleWith1(a)); 3675 const byte bytecode[] = {LOAD_CONST, 0, GET_AITER, 0, RETURN_VALUE, 0}; 3676 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3677 3678 Object result(&scope, runCode(code)); 3679 EXPECT_TRUE(isIntEqualsWord(*result, 42)); 3680} 3681 3682TEST_F(InterpreterTest, GetAiterOnNonIterable) { 3683 HandleScope scope(thread_); 3684 Object obj(&scope, SmallInt::fromWord(123)); 3685 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 3686 const byte bytecode[] = {LOAD_CONST, 0, GET_AITER, 0, RETURN_VALUE, 0}; 3687 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3688 3689 Object result(&scope, runCode(code)); 3690 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 3691} 3692 3693TEST_F(InterpreterTest, BeginFinallyPushesNone) { 3694 HandleScope scope(thread_); 3695 Tuple consts(&scope, runtime_->emptyTuple()); 3696 const byte bytecode[] = {BEGIN_FINALLY, 0, RETURN_VALUE, 0}; 3697 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3698 Object result(&scope, runCode(code)); 3699 EXPECT_TRUE(result.isNoneType()); 3700} 3701 3702TEST_F(InterpreterTest, CallFinallyPushesNextPC) { 3703 HandleScope scope(thread_); 3704 Object obj(&scope, SmallInt::fromWord(123)); 3705 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 3706 const byte bytecode[] = {CALL_FINALLY, 2, LOAD_CONST, 0, RETURN_VALUE, 0}; 3707 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3708 Object result(&scope, runCode(code)); 3709 // Address of LOAD_CONST 3710 EXPECT_TRUE(isIntEqualsWord(*result, kCodeUnitSize)); 3711} 3712 3713TEST_F(InterpreterTest, CallFinallyJumpsWithArgDelta) { 3714 HandleScope scope(thread_); 3715 Object obj(&scope, SmallInt::fromWord(123)); 3716 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 3717 const byte bytecode[] = {CALL_FINALLY, 2, RETURN_VALUE, 0, 3718 LOAD_CONST, 0, RETURN_VALUE, 0}; 3719 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3720 Object result(&scope, runCode(code)); 3721 // Result of LOAD_CONST 3722 EXPECT_TRUE(isIntEqualsWord(*result, 123)); 3723} 3724 3725TEST_F(InterpreterTest, PopFinallyWithNoneExcAndZeroArgPopsExc) { 3726 HandleScope scope(thread_); 3727 Object return_value(&scope, SmallInt::fromWord(123)); 3728 Object exc(&scope, NoneType::object()); 3729 Tuple consts(&scope, runtime_->newTupleWith2(return_value, exc)); 3730 const byte bytecode[] = {// Load return value 3731 LOAD_CONST, 0, 3732 // Load exc 3733 LOAD_CONST, 1, 3734 // 0 means don't pop from the stack 3735 POP_FINALLY, 0, RETURN_VALUE, 0}; 3736 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3737 Object result(&scope, runCode(code)); 3738 EXPECT_TRUE(isIntEqualsWord(*result, 123)); 3739} 3740 3741TEST_F(InterpreterTest, PopFinallyWithNoneExcAndNonzeroArgPopsExc) { 3742 HandleScope scope(thread_); 3743 Object obj(&scope, SmallInt::fromWord(123)); 3744 Object exc(&scope, NoneType::object()); 3745 Object return_value(&scope, SmallInt::fromWord(456)); 3746 Tuple consts(&scope, runtime_->newTupleWith3(obj, exc, return_value)); 3747 const byte bytecode[] = { 3748 // Load some random stuff onto the stack 3749 LOAD_CONST, 0, 3750 // Load exc 3751 LOAD_CONST, 1, 3752 // Load return value 3753 LOAD_CONST, 2, 3754 // 1 means pop first before fetching exc, and then push after 3755 POP_FINALLY, 1, RETURN_VALUE, 0}; 3756 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3757 Object result(&scope, runCode(code)); 3758 EXPECT_TRUE(isIntEqualsWord(*result, 456)); 3759} 3760 3761TEST_F(InterpreterTest, PopFinallyWithIntExcAndZeroArgPopsExc) { 3762 HandleScope scope(thread_); 3763 Object return_value(&scope, SmallInt::fromWord(123)); 3764 Object exc(&scope, SmallInt::fromWord(456)); 3765 Tuple consts(&scope, runtime_->newTupleWith2(return_value, exc)); 3766 const byte bytecode[] = {// Load return value 3767 LOAD_CONST, 0, 3768 // Load exc 3769 LOAD_CONST, 1, 3770 // 0 means don't pop from the stack 3771 POP_FINALLY, 0, RETURN_VALUE, 0}; 3772 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3773 Object result(&scope, runCode(code)); 3774 EXPECT_TRUE(isIntEqualsWord(*result, 123)); 3775} 3776 3777TEST_F(InterpreterTest, PopFinallyWithIntExcAndNonzeroArgPopsExc) { 3778 HandleScope scope(thread_); 3779 Object obj(&scope, SmallInt::fromWord(123)); 3780 Object exc(&scope, SmallInt::fromWord(456)); 3781 Object return_value(&scope, SmallInt::fromWord(789)); 3782 Tuple consts(&scope, runtime_->newTupleWith3(obj, exc, return_value)); 3783 const byte bytecode[] = { 3784 // Load some random stuff onto the stack 3785 LOAD_CONST, 0, 3786 // Load exc 3787 LOAD_CONST, 1, 3788 // Load return value 3789 LOAD_CONST, 2, 3790 // 1 means pop first before fetching exc, and then push after 3791 POP_FINALLY, 1, RETURN_VALUE, 0}; 3792 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3793 Object result(&scope, runCode(code)); 3794 EXPECT_TRUE(isIntEqualsWord(*result, 789)); 3795} 3796 3797TEST_F(InterpreterTest, PopFinallyWithNonExceptHandlerRaisesSystemError) { 3798 HandleScope scope(thread_); 3799 Object obj1(&scope, SmallInt::fromWord(1)); 3800 Object obj2(&scope, SmallInt::fromWord(2)); 3801 Object exc_type(&scope, SmallInt::fromWord(3)); 3802 Object exc_value(&scope, SmallInt::fromWord(4)); 3803 Object exc_tb(&scope, SmallInt::fromWord(5)); 3804 Object exc(&scope, SmallStr::fromCStr("exc")); 3805 Object return_value(&scope, SmallInt::fromWord(7)); 3806 Tuple consts(&scope, 3807 runtime_->newTupleWithN(7, &obj1, &obj2, &exc_type, &exc_value, 3808 &exc_tb, &exc, &return_value)); 3809 const byte bytecode[] = { 3810 // Load return value 3811 LOAD_CONST, 6, 3812 // Load exc traceback 3813 LOAD_CONST, 4, 3814 // Load exc value 3815 LOAD_CONST, 3, 3816 // Load exc type 3817 LOAD_CONST, 2, 3818 // Load ignored object 3819 LOAD_CONST, 0, 3820 // Load ignored object 3821 LOAD_CONST, 1, 3822 // Load exc 3823 LOAD_CONST, 5, 3824 // Push a non-ExceptHandler TryBlock on the block stack 3825 SETUP_FINALLY, 0, POP_FINALLY, 0, RETURN_VALUE, 0}; 3826 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3827 EXPECT_TRUE(raisedWithStr(runCode(code), LayoutId::kSystemError, 3828 "popped block is not an except handler")); 3829} 3830 3831TEST_F(InterpreterTest, EndAsyncForWithExceptionRaises) { 3832 HandleScope scope(thread_); 3833 const byte bytecode[] = { 3834 LOAD_CONST, 0, // exc_traceback 3835 LOAD_CONST, 1, // exc_value 3836 LOAD_CONST, 2, // exc_type 3837 END_ASYNC_FOR, 0, 3838 }; 3839 Object exc_traceback(&scope, runtime_->newTraceback()); 3840 Object exc_type(&scope, runtime_->typeAt(LayoutId::kUserWarning)); 3841 Object exc_value(&scope, runtime_->newStrFromCStr("exc message")); 3842 Tuple consts(&scope, 3843 runtime_->newTupleWith3(exc_traceback, exc_value, exc_type)); 3844 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3845 EXPECT_TRUE( 3846 raisedWithStr(runCode(code), LayoutId::kUserWarning, "exc message")); 3847} 3848 3849TEST_F(InterpreterTest, EndAsyncForWithStopAsyncIterationContinues) { 3850 HandleScope scope(thread_); 3851 const byte bytecode[] = { 3852 LOAD_CONST, 5, // dummy 3853 SETUP_FINALLY, 10, LOAD_CONST, 0, // exc_traceback 3854 LOAD_CONST, 1, // exc_value 3855 LOAD_CONST, 2, // exc_type 3856 LOAD_CONST, 3, // stop_async_iteration 3857 RAISE_VARARGS, 1, END_ASYNC_FOR, 4, LOAD_CONST, 5, // dummy 3858 RETURN_VALUE, 0, LOAD_CONST, 4, // 42 3859 RETURN_VALUE, 0, 3860 }; 3861 Object exc_traceback(&scope, runtime_->newTraceback()); 3862 Object exc_value(&scope, runtime_->newStrFromCStr("exc message")); 3863 Object exc_type(&scope, runtime_->typeAt(LayoutId::kUserWarning)); 3864 Object stop_async_iteration(&scope, 3865 runtime_->typeAt(LayoutId::kStopAsyncIteration)); 3866 Object value(&scope, runtime_->newInt(42)); 3867 Object dummy(&scope, runtime_->newInt(-7)); 3868 Tuple consts(&scope, 3869 runtime_->newTupleWithN(6, &exc_traceback, &exc_value, &exc_type, 3870 &stop_async_iteration, &value, &dummy)); 3871 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3872 EXPECT_TRUE(isIntEqualsWord(runCode(code), 42)); 3873} 3874 3875TEST_F(InterpreterTest, BeforeAsyncWithCallsDunderAenter) { 3876 HandleScope scope(thread_); 3877 ASSERT_FALSE(runFromCStr(runtime_, R"( 3878enter = None 3879exit = None 3880 3881class M: 3882 def __aenter__(self): 3883 global enter 3884 enter = self 3885 3886 def __aexit__(self, exc_type, exc_value, traceback): 3887 global exit 3888 exit = self 3889 3890manager = M() 3891 )") 3892 .isError()); 3893 Object manager(&scope, mainModuleAt(runtime_, "manager")); 3894 Object main_obj(&scope, findMainModule(runtime_)); 3895 ASSERT_TRUE(main_obj.isModule()); 3896 3897 Object obj(&scope, SmallInt::fromWord(42)); 3898 Tuple consts(&scope, runtime_->newTupleWith2(obj, manager)); 3899 const byte bytecode[] = {LOAD_CONST, 1, BEFORE_ASYNC_WITH, 0, POP_TOP, 0, 3900 LOAD_CONST, 0, RETURN_VALUE, 0}; 3901 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3902 3903 EXPECT_TRUE(isIntEqualsWord(runCode(code), 42)); 3904 Object enter(&scope, mainModuleAt(runtime_, "enter")); 3905 EXPECT_EQ(*enter, *manager); 3906 Object exit(&scope, mainModuleAt(runtime_, "exit")); 3907 EXPECT_EQ(*exit, NoneType::object()); 3908} 3909 3910TEST_F(InterpreterTest, BeforeAsyncWithRaisesAttributeErrorIfAexitNotDefined) { 3911 HandleScope scope(thread_); 3912 ASSERT_FALSE(runFromCStr(runtime_, R"( 3913class M: 3914 pass 3915 3916manager = M() 3917 )") 3918 .isError()); 3919 3920 Object manager(&scope, mainModuleAt(runtime_, "manager")); 3921 Tuple consts(&scope, runtime_->newTupleWith1(manager)); 3922 const byte bytecode[] = {LOAD_CONST, 0, BEFORE_ASYNC_WITH, 0}; 3923 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3924 3925 EXPECT_TRUE(raisedWithStr(runCode(code), LayoutId::kAttributeError, 3926 "'M' object has no attribute '__aexit__'")); 3927} 3928 3929TEST_F(InterpreterTest, BeforeAsyncWithRaisesAttributeErrorIfAenterNotDefined) { 3930 HandleScope scope(thread_); 3931 ASSERT_FALSE(runFromCStr(runtime_, R"( 3932class M: 3933 def __aexit__(self): 3934 pass 3935 3936manager = M() 3937 )") 3938 .isError()); 3939 3940 Object manager(&scope, mainModuleAt(runtime_, "manager")); 3941 Tuple consts(&scope, runtime_->newTupleWith1(manager)); 3942 const byte bytecode[] = {LOAD_CONST, 0, BEFORE_ASYNC_WITH, 0}; 3943 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3944 3945 EXPECT_TRUE(raisedWithStr(runCode(code), LayoutId::kAttributeError, 3946 "'M' object has no attribute '__aenter__'")); 3947} 3948 3949TEST_F(InterpreterTest, 3950 BeforeAsyncWithPropagatesExceptionIfResolvingAexitDynamicallyRaises) { 3951 HandleScope scope(thread_); 3952 ASSERT_FALSE(runFromCStr(runtime_, R"( 3953class A: 3954 def __get__(self, obj, type=None): 3955 raise RuntimeError("foo") 3956 3957class M: 3958 __aexit__ = A() 3959 3960 async def __aenter__(self): 3961 pass 3962 3963manager = M() 3964 )") 3965 .isError()); 3966 3967 Object manager(&scope, mainModuleAt(runtime_, "manager")); 3968 Tuple consts(&scope, runtime_->newTupleWith1(manager)); 3969 const byte bytecode[] = {LOAD_CONST, 0, BEFORE_ASYNC_WITH, 0}; 3970 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3971 3972 EXPECT_TRUE(raisedWithStr(runCode(code), LayoutId::kRuntimeError, "foo")); 3973} 3974 3975TEST_F(InterpreterTest, 3976 BeforeAsyncWithPropagatesExceptionIfResolvingAenterDynamicallyRaises) { 3977 HandleScope scope(thread_); 3978 ASSERT_FALSE(runFromCStr(runtime_, R"( 3979class A: 3980 def __get__(self, obj, type=None): 3981 raise RuntimeError("foo") 3982 3983class M: 3984 __aenter__ = A() 3985 3986 async def __aexit__(self, a, b, c): 3987 pass 3988 3989manager = M() 3990 )") 3991 .isError()); 3992 3993 Object manager(&scope, mainModuleAt(runtime_, "manager")); 3994 Tuple consts(&scope, runtime_->newTupleWith1(manager)); 3995 const byte bytecode[] = {LOAD_CONST, 0, BEFORE_ASYNC_WITH, 0}; 3996 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 3997 3998 EXPECT_TRUE(raisedWithStr(runCode(code), LayoutId::kRuntimeError, "foo")); 3999} 4000 4001TEST_F(InterpreterTest, SetupAsyncWithPushesBlock) { 4002 HandleScope scope(thread_); 4003 Object obj(&scope, SmallInt::fromWord(42)); 4004 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 4005 const byte bytecode[] = { 4006 LOAD_CONST, 0, SETUP_ASYNC_WITH, 0, POP_BLOCK, 0, RETURN_VALUE, 0, 4007 }; 4008 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 4009 EXPECT_EQ(runCode(code), SmallInt::fromWord(42)); 4010} 4011 4012TEST_F(InterpreterTest, UnpackSequenceEx) { 4013 HandleScope scope(thread_); 4014 ASSERT_FALSE(runFromCStr(runtime_, R"( 4015l = [1, 2, 3, 4, 5, 6, 7] 4016a, b, c, *d, e, f, g = l 4017)") 4018 .isError()); 4019 Object a(&scope, mainModuleAt(runtime_, "a")); 4020 Object b(&scope, mainModuleAt(runtime_, "b")); 4021 Object c(&scope, mainModuleAt(runtime_, "c")); 4022 EXPECT_TRUE(isIntEqualsWord(*a, 1)); 4023 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 4024 EXPECT_TRUE(isIntEqualsWord(*c, 3)); 4025 4026 Object d(&scope, mainModuleAt(runtime_, "d")); 4027 ASSERT_TRUE(d.isList()); 4028 List list(&scope, *d); 4029 EXPECT_EQ(list.numItems(), 1); 4030 EXPECT_TRUE(isIntEqualsWord(list.at(0), 4)); 4031 4032 Object e(&scope, mainModuleAt(runtime_, "e")); 4033 Object f(&scope, mainModuleAt(runtime_, "f")); 4034 Object g(&scope, mainModuleAt(runtime_, "g")); 4035 EXPECT_TRUE(isIntEqualsWord(*e, 5)); 4036 EXPECT_TRUE(isIntEqualsWord(*f, 6)); 4037 EXPECT_TRUE(isIntEqualsWord(*g, 7)); 4038} 4039 4040TEST_F(InterpreterTest, UnpackSequenceExWithSeqIterator) { 4041 HandleScope scope(thread_); 4042 ASSERT_FALSE(runFromCStr(runtime_, R"( 4043class Seq: 4044 def __getitem__(s, i): 4045 return ("foo", "bar", 42)[i] 4046a, *b = Seq() 4047)") 4048 .isError()); 4049 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "a"), "foo")); 4050 Object b(&scope, mainModuleAt(runtime_, "b")); 4051 EXPECT_PYLIST_EQ(b, {"bar", 42}); 4052} 4053 4054TEST_F(InterpreterTest, UnpackSequenceExWithNoElementsAfter) { 4055 HandleScope scope(thread_); 4056 ASSERT_FALSE(runFromCStr(runtime_, R"( 4057l = [1, 2, 3, 4] 4058a, b, *c = l 4059)") 4060 .isError()); 4061 Object a(&scope, mainModuleAt(runtime_, "a")); 4062 Object b(&scope, mainModuleAt(runtime_, "b")); 4063 Object c(&scope, mainModuleAt(runtime_, "c")); 4064 EXPECT_TRUE(isIntEqualsWord(*a, 1)); 4065 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 4066 4067 ASSERT_TRUE(c.isList()); 4068 List list(&scope, *c); 4069 ASSERT_EQ(list.numItems(), 2); 4070 EXPECT_TRUE(isIntEqualsWord(list.at(0), 3)); 4071 EXPECT_TRUE(isIntEqualsWord(list.at(1), 4)); 4072} 4073 4074TEST_F(InterpreterTest, UnpackSequenceExWithNoElementsBefore) { 4075 HandleScope scope(thread_); 4076 ASSERT_FALSE(runFromCStr(runtime_, R"( 4077l = [1, 2, 3, 4] 4078*a, b, c = l 4079)") 4080 .isError()); 4081 Object a(&scope, mainModuleAt(runtime_, "a")); 4082 Object b(&scope, mainModuleAt(runtime_, "b")); 4083 Object c(&scope, mainModuleAt(runtime_, "c")); 4084 ASSERT_TRUE(a.isList()); 4085 List list(&scope, *a); 4086 ASSERT_EQ(list.numItems(), 2); 4087 EXPECT_TRUE(isIntEqualsWord(list.at(0), 1)); 4088 EXPECT_TRUE(isIntEqualsWord(list.at(1), 2)); 4089 4090 EXPECT_TRUE(isIntEqualsWord(*b, 3)); 4091 EXPECT_TRUE(isIntEqualsWord(*c, 4)); 4092} 4093 4094TEST_F(InterpreterTest, BuildMapCallsDunderHashAndPropagatesException) { 4095 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4096class C: 4097 def __hash__(self): 4098 raise ValueError('foo') 4099d = {C(): 4} 4100)"), 4101 LayoutId::kValueError, "foo")); 4102} 4103 4104TEST_F(InterpreterTest, BuildMapUnpackWithDict) { 4105 HandleScope scope(thread_); 4106 ASSERT_FALSE(runFromCStr(runtime_, R"( 4107d = {**{'a': 1, 'b': 2}, 'c': 3, **{'d': 4}} 4108)") 4109 .isError()); 4110 4111 Object d(&scope, mainModuleAt(runtime_, "d")); 4112 ASSERT_TRUE(d.isDict()); 4113 4114 Dict dict(&scope, *d); 4115 EXPECT_EQ(dict.numItems(), 4); 4116 4117 Str name(&scope, runtime_->newStrFromCStr("a")); 4118 Object el0(&scope, dictAtByStr(thread_, dict, name)); 4119 EXPECT_TRUE(isIntEqualsWord(*el0, 1)); 4120 4121 name = runtime_->newStrFromCStr("b"); 4122 Object el1(&scope, dictAtByStr(thread_, dict, name)); 4123 EXPECT_TRUE(isIntEqualsWord(*el1, 2)); 4124 4125 name = runtime_->newStrFromCStr("c"); 4126 Object el2(&scope, dictAtByStr(thread_, dict, name)); 4127 EXPECT_TRUE(isIntEqualsWord(*el2, 3)); 4128 4129 name = runtime_->newStrFromCStr("d"); 4130 Object el3(&scope, dictAtByStr(thread_, dict, name)); 4131 EXPECT_TRUE(isIntEqualsWord(*el3, 4)); 4132} 4133 4134TEST_F(InterpreterTest, BuildMapUnpackWithListKeysMapping) { 4135 HandleScope scope(thread_); 4136 ASSERT_FALSE(runFromCStr(runtime_, R"( 4137class Foo: 4138 def __init__(self): 4139 self.idx = 0 4140 self._items = [('a', 1), ('b', 2), ('c', 3)] 4141 4142 def keys(self): 4143 return [x[0] for x in self._items] 4144 4145 def __getitem__(self, key): 4146 for k, v in self._items: 4147 if key == k: 4148 return v 4149 raise KeyError() 4150 4151d = {**Foo(), 'd': 4} 4152)") 4153 .isError()); 4154 4155 Object d(&scope, mainModuleAt(runtime_, "d")); 4156 ASSERT_TRUE(d.isDict()); 4157 4158 Dict dict(&scope, *d); 4159 EXPECT_EQ(dict.numItems(), 4); 4160 4161 Str name(&scope, runtime_->newStrFromCStr("a")); 4162 Object el0(&scope, dictAtByStr(thread_, dict, name)); 4163 EXPECT_TRUE(isIntEqualsWord(*el0, 1)); 4164 4165 name = runtime_->newStrFromCStr("b"); 4166 Object el1(&scope, dictAtByStr(thread_, dict, name)); 4167 EXPECT_TRUE(isIntEqualsWord(*el1, 2)); 4168 4169 name = runtime_->newStrFromCStr("c"); 4170 Object el2(&scope, dictAtByStr(thread_, dict, name)); 4171 EXPECT_TRUE(isIntEqualsWord(*el2, 3)); 4172 4173 name = runtime_->newStrFromCStr("d"); 4174 Object el3(&scope, dictAtByStr(thread_, dict, name)); 4175 EXPECT_TRUE(isIntEqualsWord(*el3, 4)); 4176} 4177 4178TEST_F(InterpreterTest, BuildMapUnpackWithTupleKeysMapping) { 4179 HandleScope scope(thread_); 4180 ASSERT_FALSE(runFromCStr(runtime_, R"( 4181class Foo: 4182 def __init__(self): 4183 self.idx = 0 4184 self._items = [('a', 1), ('b', 2), ('c', 3)] 4185 4186 def keys(self): 4187 return ('a', 'b', 'c') 4188 4189 def __getitem__(self, key): 4190 for k, v in self._items: 4191 if key == k: 4192 return v 4193 raise KeyError() 4194 4195d = {**Foo(), 'd': 4} 4196)") 4197 .isError()); 4198 4199 Object d(&scope, mainModuleAt(runtime_, "d")); 4200 ASSERT_TRUE(d.isDict()); 4201 4202 Dict dict(&scope, *d); 4203 EXPECT_EQ(dict.numItems(), 4); 4204 4205 Str name(&scope, runtime_->newStrFromCStr("a")); 4206 Object el0(&scope, dictAtByStr(thread_, dict, name)); 4207 EXPECT_TRUE(isIntEqualsWord(*el0, 1)); 4208 4209 name = runtime_->newStrFromCStr("b"); 4210 Object el1(&scope, dictAtByStr(thread_, dict, name)); 4211 EXPECT_TRUE(isIntEqualsWord(*el1, 2)); 4212 4213 name = runtime_->newStrFromCStr("c"); 4214 Object el2(&scope, dictAtByStr(thread_, dict, name)); 4215 EXPECT_TRUE(isIntEqualsWord(*el2, 3)); 4216 4217 name = runtime_->newStrFromCStr("d"); 4218 Object el3(&scope, dictAtByStr(thread_, dict, name)); 4219 EXPECT_TRUE(isIntEqualsWord(*el3, 4)); 4220} 4221 4222TEST_F(InterpreterTest, BuildMapUnpackWithIterableKeysMapping) { 4223 HandleScope scope(thread_); 4224 ASSERT_FALSE(runFromCStr(runtime_, R"( 4225class KeysIter: 4226 def __init__(self, keys): 4227 self.idx = 0 4228 self.keys = keys 4229 4230 def __iter__(self): 4231 return self 4232 4233 def __next__(self): 4234 if self.idx == len(self.keys): 4235 raise StopIteration 4236 r = self.keys[self.idx] 4237 self.idx += 1 4238 return r 4239 4240class Foo: 4241 def __init__(self): 4242 self.idx = 0 4243 self._items = [('a', 1), ('b', 2), ('c', 3)] 4244 4245 def keys(self): 4246 return KeysIter([x[0] for x in self._items]) 4247 4248 def __getitem__(self, key): 4249 for k, v in self._items: 4250 if key == k: 4251 return v 4252 raise KeyError() 4253 4254d = {**Foo(), 'd': 4} 4255)") 4256 .isError()); 4257 4258 Object d(&scope, mainModuleAt(runtime_, "d")); 4259 ASSERT_TRUE(d.isDict()); 4260 4261 Dict dict(&scope, *d); 4262 EXPECT_EQ(dict.numItems(), 4); 4263 4264 Str name(&scope, runtime_->newStrFromCStr("a")); 4265 Object el0(&scope, dictAtByStr(thread_, dict, name)); 4266 EXPECT_TRUE(isIntEqualsWord(*el0, 1)); 4267 4268 name = runtime_->newStrFromCStr("b"); 4269 Object el1(&scope, dictAtByStr(thread_, dict, name)); 4270 EXPECT_TRUE(isIntEqualsWord(*el1, 2)); 4271 4272 name = runtime_->newStrFromCStr("c"); 4273 Object el2(&scope, dictAtByStr(thread_, dict, name)); 4274 EXPECT_TRUE(isIntEqualsWord(*el2, 3)); 4275 4276 name = runtime_->newStrFromCStr("d"); 4277 Object el3(&scope, dictAtByStr(thread_, dict, name)); 4278 EXPECT_TRUE(isIntEqualsWord(*el3, 4)); 4279} 4280 4281TEST_F(InterpreterTest, BuildMapUnpackWithNonMapping) { 4282 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4283class Foo: 4284 pass 4285 4286d = {**Foo(), 'd': 4} 4287 )"), 4288 LayoutId::kTypeError, 4289 "'Foo' object is not a mapping")); 4290} 4291 4292TEST_F(InterpreterTest, BuildMapUnpackWithUnsubscriptableMapping) { 4293 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4294class Foo: 4295 def __init__(self): 4296 self.idx = 0 4297 self._items = [('a', 1), ('b', 2), ('c', 3)] 4298 4299 def keys(self): 4300 return ('a', 'b', 'c') 4301 4302d = {**Foo(), 'd': 4} 4303 )"), 4304 LayoutId::kTypeError, 4305 "'Foo' object is not a mapping")); 4306} 4307 4308TEST_F(InterpreterTest, BuildMapUnpackWithNonIterableKeys) { 4309 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4310class Foo: 4311 def __init__(self): 4312 self.idx = 0 4313 self._items = [('a', 1), ('b', 2), ('c', 3)] 4314 4315 def keys(self): 4316 return None 4317 4318 def __getitem__(self, key): 4319 pass 4320 4321d = {**Foo(), 'd': 4} 4322 )"), 4323 LayoutId::kTypeError, "keys() is not iterable")); 4324} 4325 4326TEST_F(InterpreterTest, BuildMapUnpackWithBadIteratorKeys) { 4327 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4328class KeysIter: 4329 def __iter__(self): 4330 return self 4331 4332class Foo: 4333 def __init__(self): 4334 pass 4335 4336 def keys(self): 4337 return KeysIter() 4338 4339 def __getitem__(self, key): 4340 pass 4341 4342d = {**Foo(), 'd': 4} 4343 )"), 4344 LayoutId::kTypeError, "keys() is not iterable")); 4345} 4346 4347TEST_F(InterpreterTest, BuildSetCallsDunderHashAndPropagatesException) { 4348 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4349class C: 4350 def __hash__(self): 4351 raise ValueError('foo') 4352s = {C()} 4353)"), 4354 LayoutId::kValueError, "foo")); 4355} 4356 4357TEST_F(InterpreterTest, UnpackSequenceExWithTooFewObjectsBefore) { 4358 const char* src = R"( 4359l = [1, 2] 4360a, b, c, *d = l 4361)"; 4362 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kValueError, 4363 "not enough values to unpack")); 4364} 4365 4366TEST_F(InterpreterTest, UnpackSequenceExWithTooFewObjectsAfter) { 4367 const char* src = R"( 4368l = [1, 2] 4369*a, b, c, d = l 4370)"; 4371 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kValueError, 4372 "not enough values to unpack")); 4373} 4374 4375TEST_F(InterpreterTest, BuildTupleUnpackWithCall) { 4376 HandleScope scope(thread_); 4377 ASSERT_FALSE(runFromCStr(runtime_, R"( 4378def foo(*args): 4379 return args 4380 4381t = foo(*(1,2), *(3, 4)) 4382)") 4383 .isError()); 4384 4385 Object t(&scope, mainModuleAt(runtime_, "t")); 4386 ASSERT_TRUE(t.isTuple()); 4387 4388 Tuple tuple(&scope, *t); 4389 EXPECT_TRUE(isIntEqualsWord(tuple.at(0), 1)); 4390 EXPECT_TRUE(isIntEqualsWord(tuple.at(1), 2)); 4391 EXPECT_TRUE(isIntEqualsWord(tuple.at(2), 3)); 4392 EXPECT_TRUE(isIntEqualsWord(tuple.at(3), 4)); 4393} 4394 4395TEST_F(InterpreterTest, FunctionDerefsVariable) { 4396 HandleScope scope(thread_); 4397 ASSERT_FALSE(runFromCStr(runtime_, R"( 4398def outer(): 4399 var = 1 4400 def inner(): 4401 return var 4402 del var 4403 return 0 4404 4405v = outer() 4406 )") 4407 .isError()); 4408 4409 Object v(&scope, mainModuleAt(runtime_, "v")); 4410 EXPECT_TRUE(isIntEqualsWord(*v, 0)); 4411} 4412 4413TEST_F(InterpreterTest, FunctionAccessesUnboundVariable) { 4414 const char* src = R"( 4415def outer(): 4416 var = 1 4417 def inner(): 4418 return var 4419 del var 4420 return var 4421 4422v = outer() 4423 )"; 4424 4425 EXPECT_TRUE( 4426 raisedWithStr(runFromCStr(runtime_, src), LayoutId::kUnboundLocalError, 4427 "local variable 'var' referenced before assignment")); 4428} 4429 4430TEST_F(InterpreterTest, ImportStarImportsPublicSymbols) { 4431 HandleScope scope(thread_); 4432 Object module_src(&scope, runtime_->newStrFromCStr(R"( 4433def public_symbol(): 4434 return 1 4435def public_symbol2(): 4436 return 2 4437)")); 4438 Object filename(&scope, runtime_->newStrFromCStr("<test string>")); 4439 4440 // Preload the module 4441 Object name(&scope, runtime_->newStrFromCStr("test_module")); 4442 Code code(&scope, compile(thread_, module_src, filename, ID(exec), 4443 /*flags=*/0, /*optimize=*/0)); 4444 ASSERT_FALSE(executeModuleFromCode(thread_, code, name).isError()); 4445 4446 ASSERT_FALSE(runFromCStr(runtime_, R"( 4447from test_module import * 4448a = public_symbol() 4449b = public_symbol2() 4450)") 4451 .isError()); 4452 4453 Object a(&scope, mainModuleAt(runtime_, "a")); 4454 Object b(&scope, mainModuleAt(runtime_, "b")); 4455 EXPECT_TRUE(isIntEqualsWord(*a, 1)); 4456 EXPECT_TRUE(isIntEqualsWord(*b, 2)); 4457} 4458 4459TEST_F(InterpreterTest, ImportStarDoesNotImportPrivateSymbols) { 4460 HandleScope scope(thread_); 4461 Object module_src(&scope, runtime_->newStrFromCStr(R"( 4462def public_symbol(): 4463 return 1 4464def _private_symbol(): 4465 return 2 4466)")); 4467 Object filename(&scope, runtime_->newStrFromCStr("<test string>")); 4468 4469 // Preload the module 4470 Object name(&scope, runtime_->newStrFromCStr("test_module")); 4471 Code code(&scope, compile(thread_, module_src, filename, ID(exec), 4472 /*flags=*/0, /*optimize=*/0)); 4473 ASSERT_FALSE(executeModuleFromCode(thread_, code, name).isError()); 4474 4475 const char* main_src = R"( 4476from test_module import * 4477a = public_symbol() 4478b = _private_symbol() 4479)"; 4480 4481 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, main_src), 4482 LayoutId::kNameError, 4483 "name '_private_symbol' is not defined")); 4484} 4485 4486TEST_F(InterpreterTest, ImportStarWorksWithDictImplicitGlobals) { 4487 HandleScope scope(thread_); 4488 Object module_src(&scope, runtime_->newStrFromCStr(R"( 4489def foo(): 4490 return "bar" 4491def baz(): 4492 return "quux" 4493)")); 4494 Object filename(&scope, runtime_->newStrFromCStr("<test string>")); 4495 4496 // Preload the module 4497 Object name(&scope, runtime_->newStrFromCStr("test_module")); 4498 Code module_code(&scope, compile(thread_, module_src, filename, ID(exec), 4499 /*flags=*/0, /*optimize=*/0)); 4500 ASSERT_FALSE(executeModuleFromCode(thread_, module_code, name).isError()); 4501 4502 const char* main_src = R"( 4503from test_module import * 4504a = foo() 4505b = baz() 4506)"; 4507 4508 Object str(&scope, runtime_->newStrFromCStr(main_src)); 4509 Code main_code(&scope, compile(thread_, str, filename, ID(exec), 4510 /*flags=*/0, /*optimize=*/0)); 4511 Module main_module(&scope, findMainModule(runtime_)); 4512 Dict implicit_globals(&scope, runtime_->newDict()); 4513 Object result(&scope, 4514 thread_->exec(main_code, main_module, implicit_globals)); 4515 EXPECT_FALSE(result.isError()); 4516 EXPECT_EQ(implicit_globals.numItems(), 4); 4517} 4518 4519TEST_F(InterpreterTest, ImportStarWorksWithUserDefinedImplicitGlobals) { 4520 HandleScope scope(thread_); 4521 Object module_src(&scope, runtime_->newStrFromCStr(R"( 4522def foo(): 4523 return "bar" 4524def baz(): 4525 return "quux" 4526)")); 4527 Object filename(&scope, runtime_->newStrFromCStr("<test string>")); 4528 4529 // Preload the module 4530 Object name(&scope, runtime_->newStrFromCStr("test_module")); 4531 Code module_code(&scope, compile(thread_, module_src, filename, ID(exec), 4532 /*flags=*/0, /*optimize=*/0)); 4533 ASSERT_FALSE(executeModuleFromCode(thread_, module_code, name).isError()); 4534 4535 EXPECT_FALSE(runFromCStr(runtime_, R"( 4536class C: 4537 def __init__(self): 4538 self.mydict = {} 4539 def __setitem__(self, key, value): 4540 self.mydict[key] = value 4541 def __getitem__(self, key): 4542 return self.mydict[key] 4543)") 4544 .isError()); 4545 4546 const char* main_src = R"( 4547from test_module import * 4548a = foo() 4549b = baz() 4550)"; 4551 4552 Object str(&scope, runtime_->newStrFromCStr(main_src)); 4553 Code main_code(&scope, compile(thread_, str, filename, ID(exec), 4554 /*flags=*/0, /*optimize=*/0)); 4555 Module main_module(&scope, findMainModule(runtime_)); 4556 Type implicit_globals_type(&scope, mainModuleAt(runtime_, "C")); 4557 Object implicit_globals( 4558 &scope, thread_->invokeMethod1(implicit_globals_type, ID(__call__))); 4559 Object result(&scope, 4560 thread_->exec(main_code, main_module, implicit_globals)); 4561 EXPECT_FALSE(result.isError()); 4562} 4563 4564TEST_F(InterpreterTest, ImportCallsBuiltinsDunderImport) { 4565 ASSERT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4566import builtins 4567def import_forbidden(name, globals, locals, fromlist, level): 4568 raise Exception("import forbidden") 4569builtins.__import__ = import_forbidden 4570import builtins 4571)"), 4572 LayoutId::kException, "import forbidden")); 4573} 4574 4575TEST_F(InterpreterTest, GetAnextCallsAnextAndAwait) { 4576 HandleScope scope(thread_); 4577 ASSERT_FALSE(runFromCStr(runtime_, R"( 4578anext_called = None 4579await_called = None 4580 4581class AsyncIterator: 4582 def __anext__(self): 4583 global anext_called 4584 anext_called = self 4585 return self 4586 4587 def __await__(self): 4588 global await_called 4589 await_called = self 4590 return self 4591 4592 # Return from __await__ must be an "iterable" type 4593 def __next__(self): 4594 pass 4595 4596a = AsyncIterator() 4597)") 4598 .isError()); 4599 Object a(&scope, mainModuleAt(runtime_, "a")); 4600 4601 Tuple consts(&scope, runtime_->newTupleWith1(a)); 4602 const byte bytecode[] = {LOAD_CONST, 0, GET_ANEXT, 0, 4603 BUILD_TUPLE, 2, RETURN_VALUE, 0}; 4604 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 4605 4606 Tuple result(&scope, runCode(code)); 4607 EXPECT_EQ(*a, result.at(0)); 4608 EXPECT_EQ(*a, result.at(1)); 4609 Object anext(&scope, mainModuleAt(runtime_, "anext_called")); 4610 EXPECT_EQ(*a, *anext); 4611 Object await(&scope, mainModuleAt(runtime_, "await_called")); 4612 EXPECT_EQ(*a, *await); 4613} 4614 4615TEST_F(InterpreterTest, GetAnextCallsAnextButNotAwaitOnAsyncGenerator) { 4616 HandleScope scope(thread_); 4617 ASSERT_FALSE(runFromCStr(runtime_, R"( 4618async def f(): 4619 yield 4620 4621async_gen = f() 4622 4623class AsyncIterator: 4624 def __anext__(self): 4625 return async_gen 4626 4627async_it = AsyncIterator() 4628)") 4629 .isError()); 4630 Object async_gen(&scope, mainModuleAt(runtime_, "async_gen")); 4631 Object async_it(&scope, mainModuleAt(runtime_, "async_it")); 4632 // The async generator object instance should not have an __await__() method. 4633 ASSERT_TRUE(Interpreter::lookupMethod(thread_, async_gen, ID(__await__)) 4634 .isErrorNotFound()); 4635 Tuple consts(&scope, runtime_->newTupleWith1(async_it)); 4636 const byte bytecode[] = {LOAD_CONST, 0, GET_ANEXT, 0, 4637 BUILD_TUPLE, 2, RETURN_VALUE, 0}; 4638 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 4639 Tuple result(&scope, runCode(code)); 4640 EXPECT_EQ(*async_it, result.at(0)); 4641 EXPECT_EQ(runtime_->typeOf(result.at(1)), 4642 runtime_->typeAt(LayoutId::kAsyncGenerator)); 4643} 4644 4645TEST_F(InterpreterTest, GetAnextOnNonIterable) { 4646 HandleScope scope(thread_); 4647 Object obj(&scope, SmallInt::fromWord(123)); 4648 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 4649 const byte bytecode[] = {LOAD_CONST, 0, GET_ANEXT, 0, RETURN_VALUE, 0}; 4650 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 4651 4652 Object result(&scope, runCode(code)); 4653 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 4654} 4655 4656TEST_F(InterpreterTest, GetAnextWithInvalidAnext) { 4657 HandleScope scope(thread_); 4658 ASSERT_FALSE(runFromCStr(runtime_, R"( 4659class AsyncIterator: 4660 def __anext__(self): 4661 return 42 4662 4663a = AsyncIterator() 4664)") 4665 .isError()); 4666 Object a(&scope, mainModuleAt(runtime_, "a")); 4667 4668 Tuple consts(&scope, runtime_->newTupleWith1(a)); 4669 const byte bytecode[] = {LOAD_CONST, 0, GET_ANEXT, 0, RETURN_VALUE, 0}; 4670 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 4671 4672 Object result(&scope, runCode(code)); 4673 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 4674} 4675 4676static RawObject runCodeCallingGetAwaitableOnObject(Thread* thread, 4677 const Object& obj) { 4678 HandleScope scope(thread); 4679 Runtime* runtime = thread->runtime(); 4680 Tuple consts(&scope, runtime->newTupleWith1(obj)); 4681 const byte bytecode[] = {LOAD_CONST, 0, GET_AWAITABLE, 0, RETURN_VALUE, 0}; 4682 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 4683 return runCode(code); 4684} 4685 4686TEST_F(InterpreterTest, GetAwaitableCallsAwait) { 4687 HandleScope scope(thread_); 4688 ASSERT_FALSE(runFromCStr(runtime_, R"( 4689# Return from __await__ must be an "iterable" type 4690iterable = iter([]) 4691 4692class Awaitable: 4693 def __await__(self): 4694 return iterable 4695 4696a = Awaitable() 4697)") 4698 .isError()); 4699 4700 Object iterable(&scope, mainModuleAt(runtime_, "iterable")); 4701 Object a(&scope, mainModuleAt(runtime_, "a")); 4702 Object result(&scope, runCodeCallingGetAwaitableOnObject(thread_, a)); 4703 EXPECT_EQ(result, iterable); 4704} 4705 4706TEST_F(InterpreterTest, GetAwaitableIsNoOpOnCoroutine) { 4707 HandleScope scope(thread_); 4708 ASSERT_FALSE(runFromCStr(runtime_, R"( 4709async def f(): pass 4710 4711coro = f() 4712)") 4713 .isError()); 4714 4715 Object coro(&scope, mainModuleAt(runtime_, "coro")); 4716 Object result(&scope, runCodeCallingGetAwaitableOnObject(thread_, coro)); 4717 EXPECT_TRUE(*result == *coro); 4718} 4719 4720TEST_F(InterpreterTest, GetAwaitableIsNoOpOnAsyncGenerator) { 4721 HandleScope scope(thread_); 4722 ASSERT_FALSE(runFromCStr(runtime_, R"( 4723async def f(): yield 4724 4725async_gen = f() 4726)") 4727 .isError()); 4728 4729 Object async_gen(&scope, mainModuleAt(runtime_, "async_gen")); 4730 Object result(&scope, runCodeCallingGetAwaitableOnObject(thread_, async_gen)); 4731 EXPECT_TRUE(*result == *async_gen); 4732} 4733 4734TEST_F(InterpreterTest, GetAwaitableRaisesOnUnflaggedGenerator) { 4735 HandleScope scope(thread_); 4736 ASSERT_FALSE(runFromCStr(runtime_, R"( 4737def f(): yield 4738 4739generator = f() 4740)") 4741 .isError()); 4742 4743 Object generator(&scope, mainModuleAt(runtime_, "generator")); 4744 Object result(&scope, runCodeCallingGetAwaitableOnObject(thread_, generator)); 4745 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 4746} 4747 4748TEST_F(InterpreterTest, GetAwaitableIsNoOpOnFlaggedGenerator) { 4749 HandleScope scope(thread_); 4750 ASSERT_FALSE(runFromCStr(runtime_, R"( 4751def f(): yield 4752)") 4753 .isError()); 4754 Function generator_function(&scope, mainModuleAt(runtime_, "f")); 4755 generator_function.setFlags(generator_function.flags() | 4756 RawFunction::Flags::kIterableCoroutine); 4757 ASSERT_FALSE(runFromCStr(runtime_, R"( 4758generator = f() 4759)") 4760 .isError()); 4761 Object generator(&scope, mainModuleAt(runtime_, "generator")); 4762 Object result(&scope, runCodeCallingGetAwaitableOnObject(thread_, generator)); 4763 EXPECT_TRUE(*result == *generator); 4764} 4765 4766TEST_F(InterpreterTest, GetAwaitableOnNonAwaitable) { 4767 HandleScope scope(thread_); 4768 Object str(&scope, Runtime::internStrFromCStr(thread_, "foo")); 4769 Object result(&scope, runCodeCallingGetAwaitableOnObject(thread_, str)); 4770 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 4771} 4772 4773TEST_F(InterpreterTest, BuildMapUnpackWithCallDict) { 4774 HandleScope scope(thread_); 4775 ASSERT_FALSE(runFromCStr(runtime_, R"( 4776def foo(**kwargs): 4777 return kwargs 4778 4779d = foo(**{'a': 1, 'b': 2}, **{'c': 3, 'd': 4}) 4780)") 4781 .isError()); 4782 4783 Object d(&scope, mainModuleAt(runtime_, "d")); 4784 ASSERT_TRUE(d.isDict()); 4785 4786 Dict dict(&scope, *d); 4787 EXPECT_EQ(dict.numItems(), 4); 4788 4789 Str name(&scope, runtime_->newStrFromCStr("a")); 4790 Object el0(&scope, dictAtByStr(thread_, dict, name)); 4791 EXPECT_TRUE(isIntEqualsWord(*el0, 1)); 4792 4793 name = runtime_->newStrFromCStr("b"); 4794 Object el1(&scope, dictAtByStr(thread_, dict, name)); 4795 EXPECT_TRUE(isIntEqualsWord(*el1, 2)); 4796 4797 name = runtime_->newStrFromCStr("c"); 4798 Object el2(&scope, dictAtByStr(thread_, dict, name)); 4799 EXPECT_TRUE(isIntEqualsWord(*el2, 3)); 4800 4801 name = runtime_->newStrFromCStr("d"); 4802 Object el3(&scope, dictAtByStr(thread_, dict, name)); 4803 EXPECT_TRUE(isIntEqualsWord(*el3, 4)); 4804} 4805 4806TEST_F(InterpreterTest, BuildMapUnpackWithCallTupleKeys) { 4807 HandleScope scope(thread_); 4808 ASSERT_FALSE(runFromCStr(runtime_, R"( 4809class Foo: 4810 def __init__(self, d): 4811 self.d = d 4812 4813 def keys(self): 4814 return ('c', 'd') 4815 4816 def __getitem__(self, key): 4817 return self.d[key] 4818 4819def foo(**kwargs): 4820 return kwargs 4821 4822d = foo(**{'a': 1, 'b': 2}, **Foo({'c': 3, 'd': 4})) 4823)") 4824 .isError()); 4825 4826 Object d(&scope, mainModuleAt(runtime_, "d")); 4827 ASSERT_TRUE(d.isDict()); 4828 4829 Dict dict(&scope, *d); 4830 EXPECT_EQ(dict.numItems(), 4); 4831 4832 Str name(&scope, runtime_->newStrFromCStr("a")); 4833 Object el0(&scope, dictAtByStr(thread_, dict, name)); 4834 EXPECT_TRUE(isIntEqualsWord(*el0, 1)); 4835 4836 name = runtime_->newStrFromCStr("b"); 4837 Object el1(&scope, dictAtByStr(thread_, dict, name)); 4838 EXPECT_TRUE(isIntEqualsWord(*el1, 2)); 4839 4840 name = runtime_->newStrFromCStr("c"); 4841 Object el2(&scope, dictAtByStr(thread_, dict, name)); 4842 EXPECT_TRUE(isIntEqualsWord(*el2, 3)); 4843 4844 name = runtime_->newStrFromCStr("d"); 4845 Object el3(&scope, dictAtByStr(thread_, dict, name)); 4846 EXPECT_TRUE(isIntEqualsWord(*el3, 4)); 4847} 4848 4849TEST_F(InterpreterTest, BuildMapUnpackWithCallListKeys) { 4850 HandleScope scope(thread_); 4851 ASSERT_FALSE(runFromCStr(runtime_, R"( 4852class Foo: 4853 def __init__(self, d): 4854 self.d = d 4855 4856 def keys(self): 4857 return ['c', 'd'] 4858 4859 def __getitem__(self, key): 4860 return self.d[key] 4861 4862def foo(**kwargs): 4863 return kwargs 4864 4865d = foo(**{'a': 1, 'b': 2}, **Foo({'c': 3, 'd': 4})) 4866)") 4867 .isError()); 4868 4869 Object d(&scope, mainModuleAt(runtime_, "d")); 4870 ASSERT_TRUE(d.isDict()); 4871 4872 Dict dict(&scope, *d); 4873 EXPECT_EQ(dict.numItems(), 4); 4874 4875 Str name(&scope, runtime_->newStrFromCStr("a")); 4876 Object el0(&scope, dictAtByStr(thread_, dict, name)); 4877 EXPECT_TRUE(isIntEqualsWord(*el0, 1)); 4878 4879 name = runtime_->newStrFromCStr("b"); 4880 Object el1(&scope, dictAtByStr(thread_, dict, name)); 4881 EXPECT_TRUE(isIntEqualsWord(*el1, 2)); 4882 4883 name = runtime_->newStrFromCStr("c"); 4884 Object el2(&scope, dictAtByStr(thread_, dict, name)); 4885 EXPECT_TRUE(isIntEqualsWord(*el2, 3)); 4886 4887 name = runtime_->newStrFromCStr("d"); 4888 Object el3(&scope, dictAtByStr(thread_, dict, name)); 4889 EXPECT_TRUE(isIntEqualsWord(*el3, 4)); 4890} 4891 4892TEST_F(InterpreterTest, BuildMapUnpackWithCallIteratorKeys) { 4893 HandleScope scope(thread_); 4894 ASSERT_FALSE(runFromCStr(runtime_, R"( 4895class Iter: 4896 def __init__(self, keys): 4897 self.idx = 0 4898 self.keys = keys 4899 4900 def __iter__(self): 4901 return self 4902 4903 def __next__(self): 4904 if self.idx >= len(self.keys): 4905 raise StopIteration() 4906 r = self.keys[self.idx] 4907 self.idx += 1 4908 return r 4909 4910 def __length_hint__(self): 4911 return len(self.keys) - self.idx 4912 4913class Foo: 4914 def __init__(self, d): 4915 self.d = d 4916 4917 def keys(self): 4918 return Iter(['c', 'd']) 4919 4920 def __getitem__(self, key): 4921 return self.d[key] 4922 4923def foo(**kwargs): 4924 return kwargs 4925 4926d = foo(**{'a': 1, 'b': 2}, **Foo({'c': 3, 'd': 4})) 4927)") 4928 .isError()); 4929 4930 Object d(&scope, mainModuleAt(runtime_, "d")); 4931 ASSERT_TRUE(d.isDict()); 4932 4933 Dict dict(&scope, *d); 4934 EXPECT_EQ(dict.numItems(), 4); 4935 4936 Str name(&scope, runtime_->newStrFromCStr("a")); 4937 Object el0(&scope, dictAtByStr(thread_, dict, name)); 4938 EXPECT_TRUE(isIntEqualsWord(*el0, 1)); 4939 4940 name = runtime_->newStrFromCStr("b"); 4941 Object el1(&scope, dictAtByStr(thread_, dict, name)); 4942 EXPECT_TRUE(isIntEqualsWord(*el1, 2)); 4943 4944 name = runtime_->newStrFromCStr("c"); 4945 Object el2(&scope, dictAtByStr(thread_, dict, name)); 4946 EXPECT_TRUE(isIntEqualsWord(*el2, 3)); 4947 4948 name = runtime_->newStrFromCStr("d"); 4949 Object el3(&scope, dictAtByStr(thread_, dict, name)); 4950 EXPECT_TRUE(isIntEqualsWord(*el3, 4)); 4951} 4952 4953TEST_F(InterpreterTest, BuildMapUnpackWithCallDictNonStrKey) { 4954 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4955def foo(**kwargs): 4956 return kwargs 4957 4958foo(**{'a': 1, 'b': 2}, **{'c': 3, 4: 4}) 4959 )"), 4960 LayoutId::kTypeError, "keywords must be strings")); 4961} 4962 4963TEST_F(InterpreterTest, BuildMapUnpackWithCallDictRepeatedKeys) { 4964 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4965def foo(**kwargs): 4966 return kwargs 4967 4968foo(**{'a': 1, 'b': 2}, **{'c': 3, 'a': 4}) 4969 )"), 4970 LayoutId::kTypeError, 4971 "got multiple values for keyword argument 'a'")); 4972} 4973 4974TEST_F(InterpreterTest, BuildMapUnpackWithCallNonMapping) { 4975 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4976class Foo: 4977 pass 4978 4979def foo(**kwargs): 4980 return kwargs 4981 4982foo(**{'a': 1, 'b': 2}, **Foo()) 4983 )"), 4984 LayoutId::kTypeError, 4985 "'Foo' object is not a mapping")); 4986} 4987 4988TEST_F(InterpreterTest, BuildMapUnpackWithCallNonSubscriptable) { 4989 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 4990class Foo: 4991 def keys(self): 4992 pass 4993 4994def foo(**kwargs): 4995 return kwargs 4996 4997foo(**{'a': 1, 'b': 2}, **Foo()) 4998 )"), 4999 LayoutId::kTypeError, 5000 "'Foo' object is not a mapping")); 5001} 5002 5003TEST_F(InterpreterTest, BuildMapUnpackWithCallListKeysNonStrKey) { 5004 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5005class Foo: 5006 def keys(self): 5007 return [1] 5008 5009 def __getitem__(self, key): 5010 pass 5011 5012def foo(**kwargs): 5013 return kwargs 5014 5015foo(**{'a': 1, 'b': 2}, **Foo()) 5016 )"), 5017 LayoutId::kTypeError, "keywords must be strings")); 5018} 5019 5020TEST_F(InterpreterTest, BuildMapUnpackWithCallListKeysRepeatedKeys) { 5021 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5022class Foo: 5023 def keys(self): 5024 return ['a'] 5025 5026 def __getitem__(self, key): 5027 pass 5028 5029def foo(**kwargs): 5030 return kwargs 5031 5032foo(**{'a': 1, 'b': 2}, **Foo()) 5033 )"), 5034 LayoutId::kTypeError, 5035 "got multiple values for keyword argument 'a'")); 5036} 5037 5038TEST_F(InterpreterTest, BuildMapUnpackWithCallTupleKeysNonStrKeys) { 5039 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5040class Foo: 5041 def keys(self): 5042 return (1,) 5043 5044 def __getitem__(self, key): 5045 pass 5046 5047def foo(**kwargs): 5048 return kwargs 5049 5050foo(**{'a': 1, 'b': 2}, **Foo()) 5051 )"), 5052 LayoutId::kTypeError, "keywords must be strings")); 5053} 5054 5055TEST_F(InterpreterTest, BuildMapUnpackWithCallTupleKeysRepeatedKeys) { 5056 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5057class Foo: 5058 def keys(self): 5059 return ('a',) 5060 5061 def __getitem__(self, key): 5062 pass 5063 5064def foo(**kwargs): 5065 return kwargs 5066 5067foo(**{'a': 1, 'b': 2}, **Foo()) 5068 )"), 5069 LayoutId::kTypeError, 5070 "got multiple values for keyword argument 'a'")); 5071} 5072 5073TEST_F(InterpreterTest, BuildMapUnpackWithCallNonIterableKeys) { 5074 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5075class Foo: 5076 def keys(self): 5077 return None 5078 5079 def __getitem__(self, key): 5080 pass 5081 5082def foo(**kwargs): 5083 return kwargs 5084 5085foo(**{'a': 1, 'b': 2}, **Foo()) 5086 )"), 5087 LayoutId::kTypeError, "keys() is not iterable")); 5088} 5089 5090TEST_F(InterpreterTest, BuildMapUnpackWithCallIterableWithoutNext) { 5091 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5092class Iter: 5093 def __iter__(self): 5094 return self 5095 5096class Foo: 5097 def keys(self): 5098 return Iter() 5099 5100 def __getitem__(self, key): 5101 pass 5102 5103def foo(**kwargs): 5104 return kwargs 5105 5106foo(**{'a': 1, 'b': 2}, **Foo()) 5107 )"), 5108 LayoutId::kTypeError, "keys() is not iterable")); 5109} 5110 5111TEST_F(InterpreterTest, BuildMapUnpackWithCallIterableNonStrKey) { 5112 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5113class Iter: 5114 def __init__(self, keys): 5115 self.idx = 0 5116 self.keys = keys 5117 5118 def __iter__(self): 5119 return self 5120 5121 def __next__(self): 5122 if self.idx >= len(self.keys): 5123 raise StopIteration() 5124 r = self.keys[self.idx] 5125 self.idx += 1 5126 return r 5127 5128 def __length_hint__(self): 5129 return len(self.keys) - self.idx 5130 5131class Foo: 5132 def keys(self): 5133 return Iter((1, 2, 3)) 5134 5135 def __getitem__(self, key): 5136 return 0 5137 5138def foo(**kwargs): 5139 return kwargs 5140 5141foo(**{'a': 1, 'b': 2}, **Foo()) 5142 )"), 5143 LayoutId::kTypeError, "keywords must be strings")); 5144} 5145 5146TEST_F(InterpreterTest, BuildMapUnpackWithCallIterableRepeatedKeys) { 5147 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5148class Iter: 5149 def __init__(self, keys): 5150 self.idx = 0 5151 self.keys = keys 5152 5153 def __iter__(self): 5154 return self 5155 5156 def __next__(self): 5157 if self.idx >= len(self.keys): 5158 raise StopIteration() 5159 r = self.keys[self.idx] 5160 self.idx += 1 5161 return r 5162 5163 def __length_hint__(self): 5164 return len(self.keys) - self.idx 5165 5166class Foo: 5167 def keys(self): 5168 return Iter(('a', 'a')) 5169 5170 def __getitem__(self, key): 5171 return 0 5172 5173def foo(**kwargs): 5174 return kwargs 5175 5176foo(**{'a': 1, 'b': 2}, **Foo()) 5177 )"), 5178 LayoutId::kTypeError, 5179 "got multiple values for keyword argument 'a'")); 5180} 5181 5182TEST_F(InterpreterTest, YieldFromIterReturnsIter) { 5183 HandleScope scope(thread_); 5184 5185 ASSERT_FALSE(runFromCStr(runtime_, R"( 5186class FooIterator: 5187 def __next__(self): 5188 pass 5189 5190class Foo: 5191 def __iter__(self): 5192 return FooIterator() 5193 5194foo = Foo() 5195 )") 5196 .isError()); 5197 5198 Object foo(&scope, mainModuleAt(runtime_, "foo")); 5199 5200 // Create a code object and set the foo instance as a const 5201 Tuple consts(&scope, runtime_->newTupleWith1(foo)); 5202 5203 // Python code: 5204 // foo = Foo() 5205 // def bar(): 5206 // yield from foo 5207 const byte bytecode[] = { 5208 LOAD_CONST, 0, // (foo) 5209 GET_YIELD_FROM_ITER, 0, // iter(foo) 5210 RETURN_VALUE, 0, 5211 }; 5212 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 5213 5214 // Confirm that the returned value is the iterator of Foo 5215 Object result(&scope, runCode(code)); 5216 Type result_type(&scope, runtime_->typeOf(*result)); 5217 EXPECT_TRUE(isStrEqualsCStr(result_type.name(), "FooIterator")); 5218} 5219 5220TEST_F(InterpreterTest, YieldFromIterWithSequenceReturnsIter) { 5221 HandleScope scope(thread_); 5222 5223 ASSERT_FALSE(runFromCStr(runtime_, R"( 5224class FooSequence: 5225 def __getitem__(self, i): 5226 return ("foo", "bar")[i] 5227 5228foo = FooSequence() 5229 )") 5230 .isError()); 5231 5232 Object foo(&scope, mainModuleAt(runtime_, "foo")); 5233 5234 // Create a code object and set the foo instance as a const 5235 Tuple consts(&scope, runtime_->newTupleWith1(foo)); 5236 5237 // Python code: 5238 // foo = FooSequence() 5239 // def bar(): 5240 // yield from foo 5241 const byte bytecode[] = { 5242 LOAD_CONST, 0, // (foo) 5243 GET_YIELD_FROM_ITER, 0, // iter(foo) 5244 RETURN_VALUE, 0, 5245 }; 5246 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 5247 5248 // Confirm that the returned value is a sequence iterator 5249 Object result(&scope, runCode(code)); 5250 Type result_type(&scope, runtime_->typeOf(*result)); 5251 EXPECT_TRUE(isStrEqualsCStr(result_type.name(), "iterator")); 5252} 5253 5254TEST_F(InterpreterTest, YieldFromIterRaisesException) { 5255 const char* src = R"( 5256def yield_from_func(): 5257 yield from 1 5258 5259for i in yield_from_func(): 5260 pass 5261 )"; 5262 5263 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError, 5264 "'int' object is not iterable")); 5265} 5266 5267TEST_F(InterpreterTest, YieldFromCoroutineInNonCoroutineIterRaisesException) { 5268 const char* src = R"( 5269async def coro(): 5270 pass 5271 5272def f(): 5273 yield from coro() 5274 5275f().send(None) 5276 )"; 5277 5278 EXPECT_TRUE( 5279 raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError, 5280 "cannot 'yield from' a coroutine object in a non-coroutine " 5281 "generator")); 5282} 5283 5284TEST_F(InterpreterTest, MakeFunctionSetsDunderModule) { 5285 HandleScope scope(thread_); 5286 Object module_name(&scope, runtime_->newStrFromCStr("foo")); 5287 Object module_src(&scope, runtime_->newStrFromCStr(R"( 5288def bar(): pass 5289)")); 5290 Object filename(&scope, runtime_->newStrFromCStr("<test string>")); 5291 Code code(&scope, compile(thread_, module_src, filename, ID(exec), 5292 /*flags=*/0, /*optimize=*/0)); 5293 ASSERT_FALSE(executeModuleFromCode(thread_, code, module_name).isError()); 5294 ASSERT_FALSE(runFromCStr(runtime_, R"( 5295import foo 5296def baz(): pass 5297a = getattr(foo.bar, '__module__') 5298b = getattr(baz, '__module__') 5299)") 5300 .isError()); 5301 Object a(&scope, mainModuleAt(runtime_, "a")); 5302 ASSERT_TRUE(a.isStr()); 5303 EXPECT_TRUE(Str::cast(*a).equalsCStr("foo")); 5304 Object b(&scope, mainModuleAt(runtime_, "b")); 5305 ASSERT_TRUE(b.isStr()); 5306 EXPECT_TRUE(Str::cast(*b).equalsCStr("__main__")); 5307} 5308 5309TEST_F(InterpreterTest, MakeFunctionSetsDunderQualname) { 5310 HandleScope scope(thread_); 5311 ASSERT_FALSE(runFromCStr(runtime_, R"( 5312class Foo(): 5313 def bar(): pass 5314def baz(): pass 5315a = getattr(Foo.bar, '__qualname__') 5316b = getattr(baz, '__qualname__') 5317)") 5318 .isError()); 5319 Object a(&scope, mainModuleAt(runtime_, "a")); 5320 ASSERT_TRUE(a.isStr()); 5321 EXPECT_TRUE(Str::cast(*a).equalsCStr("Foo.bar")); 5322 Object b(&scope, mainModuleAt(runtime_, "b")); 5323 ASSERT_TRUE(b.isStr()); 5324 EXPECT_TRUE(Str::cast(*b).equalsCStr("baz")); 5325} 5326 5327TEST_F(InterpreterTest, MakeFunctionSetsDunderDoc) { 5328 HandleScope scope(thread_); 5329 ASSERT_FALSE(runFromCStr(runtime_, R"( 5330def foo(): 5331 """This is a docstring""" 5332 pass 5333def bar(): pass 5334)") 5335 .isError()); 5336 Object foo(&scope, testing::mainModuleAt(runtime_, "foo")); 5337 ASSERT_TRUE(foo.isFunction()); 5338 Object foo_docstring(&scope, Function::cast(*foo).doc()); 5339 ASSERT_TRUE(foo_docstring.isStr()); 5340 EXPECT_TRUE(Str::cast(*foo_docstring).equalsCStr("This is a docstring")); 5341 5342 Object bar(&scope, testing::mainModuleAt(runtime_, "bar")); 5343 ASSERT_TRUE(bar.isFunction()); 5344 Object bar_docstring(&scope, Function::cast(*bar).doc()); 5345 EXPECT_TRUE(bar_docstring.isNoneType()); 5346} 5347 5348TEST_F(InterpreterTest, OpcodesAreCounted) { 5349 if (useCppInterpreter()) { 5350 GTEST_SKIP(); 5351 } 5352 5353 HandleScope scope(thread_); 5354 ASSERT_FALSE(runFromCStr(runtime_, R"( 5355def a(a, b): 5356 return a + b 5357def func(): 5358 return a(7, 88) 5359)") 5360 .isError()); 5361 Object func(&scope, mainModuleAt(runtime_, "func")); 5362 EXPECT_EQ(thread_->opcodeCount(), 0); 5363 ASSERT_FALSE(Interpreter::call0(thread_, func).isError()); 5364 EXPECT_EQ(thread_->opcodeCount(), 0); 5365 5366 runtime_->interpreter()->setOpcodeCounting(true); 5367 runtime_->reinitInterpreter(); 5368 5369 word count_before = thread_->opcodeCount(); 5370 ASSERT_FALSE(Interpreter::call0(thread_, func).isError()); 5371 EXPECT_EQ(thread_->opcodeCount() - count_before, 9); 5372 5373 runtime_->interpreter()->setOpcodeCounting(false); 5374 runtime_->reinitInterpreter(); 5375 5376 count_before = thread_->opcodeCount(); 5377 ASSERT_FALSE(Interpreter::call0(thread_, func).isError()); 5378 EXPECT_EQ(thread_->opcodeCount() - count_before, 0); 5379} 5380 5381static ALIGN_16 RawObject startCounting(Thread* thread, Arguments) { 5382 thread->runtime()->interpreter()->setOpcodeCounting(true); 5383 thread->runtime()->reinitInterpreter(); 5384 return NoneType::object(); 5385} 5386 5387static ALIGN_16 RawObject stopCounting(Thread* thread, Arguments) { 5388 thread->runtime()->interpreter()->setOpcodeCounting(false); 5389 thread->runtime()->reinitInterpreter(); 5390 return NoneType::object(); 5391} 5392 5393TEST_F(InterpreterTest, ReinitInterpreterEnablesOpcodeCounting) { 5394 if (useCppInterpreter()) { 5395 GTEST_SKIP(); 5396 } 5397 5398 addBuiltin("start_counting", startCounting, {nullptr, 0}, 0); 5399 addBuiltin("stop_counting", stopCounting, {nullptr, 0}, 0); 5400 5401 EXPECT_EQ(thread_->opcodeCount(), 0); 5402 ASSERT_FALSE(runFromCStr(runtime_, R"( 5403def bar(): 5404 start_counting() 5405def func(): 5406 x = 5 5407 x = 5 5408 x = 5 5409 x = 5 5410 x = 5 5411 x = 5 5412 x = 5 5413 x = 5 5414 x = 5 5415 x = 5 5416 return 5 5417func() 5418bar() 5419func() 5420stop_counting() 5421func() 5422)") 5423 .isError()); 5424 // I do not want to hardcode opcode counts for the calls here (since that 5425 // may change in the future). So this just checks that we have at least 5426 // 10*2 = 20 opcodes for a `func()` call, but no more than double that amount 5427 // to make sure we did not consider the `foo()` call before and after 5428 // counting was enabled. 5429 word count = thread_->opcodeCount(); 5430 EXPECT_TRUE(20 < count && count < 40); 5431} 5432 5433TEST_F(InterpreterTest, FunctionCallWithNonFunctionRaisesTypeError) { 5434 HandleScope scope(thread_); 5435 Str not_a_func(&scope, Str::empty()); 5436 thread_->stackPush(*not_a_func); 5437 EXPECT_TRUE(raised(Interpreter::call(thread_, 0), LayoutId::kTypeError)); 5438} 5439 5440TEST_F(InterpreterTest, FunctionCallExWithNonFunctionRaisesTypeError) { 5441 HandleScope scope(thread_); 5442 Str not_a_func(&scope, Str::empty()); 5443 thread_->stackPush(*not_a_func); 5444 Tuple empty_args(&scope, runtime_->emptyTuple()); 5445 thread_->stackPush(*empty_args); 5446 EXPECT_TRUE(raisedWithStr(Interpreter::callEx(thread_, 0), 5447 LayoutId::kTypeError, 5448 "'str' object is not callable")); 5449} 5450 5451TEST_F(InterpreterTest, CallExWithDescriptorDunderCall) { 5452 ASSERT_FALSE(runFromCStr(runtime_, R"( 5453class FakeFunc: 5454 def __get__(self, obj, owner): 5455 return self 5456 def __call__(self, arg): 5457 return arg 5458 5459class C: 5460 __call__ = FakeFunc() 5461 5462args = ["hello!"] 5463result = C()(*args) 5464)") 5465 .isError()); 5466 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "hello!")); 5467} 5468 5469TEST_F(InterpreterTest, DoDeleteNameOnDictSubclass) { 5470 ASSERT_FALSE(runFromCStr(runtime_, R"( 5471class MyDict(dict): pass 5472class Meta(type): 5473 @classmethod 5474 def __prepare__(cls, *args, **kwargs): 5475 d = MyDict() 5476 d['x'] = 42 5477 return d 5478class C(metaclass=Meta): 5479 del x 5480)") 5481 .isError()); 5482} 5483 5484TEST_F(InterpreterTest, DoStoreNameOnDictSubclass) { 5485 ASSERT_FALSE(runFromCStr(runtime_, R"( 5486class MyDict(dict): pass 5487class Meta(type): 5488 @classmethod 5489 def __prepare__(cls, *args, **kwargs): 5490 return MyDict() 5491class C(metaclass=Meta): 5492 x = 42 5493)") 5494 .isError()); 5495} 5496 5497TEST_F(InterpreterTest, StoreSubscr) { 5498 ASSERT_FALSE(runFromCStr(runtime_, R"( 5499l = [0] 5500for i in range(5): 5501 l[0] += i 5502)") 5503 .isError()); 5504 5505 HandleScope scope(thread_); 5506 Object l_obj(&scope, testing::mainModuleAt(runtime_, "l")); 5507 ASSERT_TRUE(l_obj.isList()); 5508 List l(&scope, *l_obj); 5509 ASSERT_EQ(l.numItems(), 1); 5510 EXPECT_EQ(l.at(0), SmallInt::fromWord(10)); 5511} 5512 5513TEST_F(InterpreterTest, StoreSubscrWithListRewritesToStoreSubscrList) { 5514 HandleScope scope(thread_); 5515 ASSERT_FALSE(runFromCStr(runtime_, R"( 5516def foo(l, i): 5517 l[i] = 4 5518 return 100 5519 5520l = [1,2,3] 5521d = {1: -1} 5522)") 5523 .isError()); 5524 Function foo(&scope, mainModuleAt(runtime_, "foo")); 5525 MutableBytes rewritten(&scope, foo.rewrittenBytecode()); 5526 ASSERT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_ANAMORPHIC); 5527 5528 List l(&scope, mainModuleAt(runtime_, "l")); 5529 SmallInt key(&scope, SmallInt::fromWord(1)); 5530 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, l, key), 100)); 5531 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_LIST); 5532 5533 // Revert back to caching __getitem__ when a non-list is observed. 5534 Dict d(&scope, mainModuleAt(runtime_, "d")); 5535 EXPECT_TRUE(isIntEqualsWord(Interpreter::call2(thread_, foo, d, key), 100)); 5536 EXPECT_EQ(rewrittenBytecodeOpAt(rewritten, 3), STORE_SUBSCR_MONOMORPHIC); 5537} 5538 5539// TODO(bsimmers) Rewrite these exception tests to ensure that the specific 5540// bytecodes we care about are being exercised, so we're not be at the mercy of 5541// compiler optimizations or changes. 5542TEST_F(InterpreterTest, ExceptCatchesException) { 5543 ASSERT_FALSE(runFromCStr(runtime_, R"( 5544n = 0 5545try: 5546 raise RuntimeError("something went wrong") 5547 n = 1 5548except: 5549 if n == 0: 5550 n = 2 5551)") 5552 .isError()); 5553 5554 HandleScope scope(thread_); 5555 Object n(&scope, testing::mainModuleAt(runtime_, "n")); 5556 EXPECT_TRUE(isIntEqualsWord(*n, 2)); 5557} 5558 5559TEST_F(InterpreterTest, RaiseCrossesFunctions) { 5560 ASSERT_FALSE(runFromCStr(runtime_, R"( 5561def sub(): 5562 raise RuntimeError("from sub") 5563 5564def main(): 5565 sub() 5566 5567n = 0 5568try: 5569 main() 5570 n = 1 5571except: 5572 if n == 0: 5573 n = 2 5574)") 5575 .isError()); 5576 5577 HandleScope scope(thread_); 5578 Object n(&scope, testing::mainModuleAt(runtime_, "n")); 5579 EXPECT_TRUE(isIntEqualsWord(*n, 2)); 5580} 5581 5582TEST_F(InterpreterTest, RaiseFromSetsCause) { 5583 ASSERT_FALSE(runFromCStr(runtime_, R"( 5584try: 5585 try: 5586 raise RuntimeError 5587 except Exception as e: 5588 raise TypeError from e 5589except Exception as e: 5590 exc = e 5591)") 5592 .isError()); 5593 5594 HandleScope scope(thread_); 5595 Object exc_obj(&scope, testing::mainModuleAt(runtime_, "exc")); 5596 ASSERT_EQ(exc_obj.layoutId(), LayoutId::kTypeError); 5597 BaseException exc(&scope, *exc_obj); 5598 EXPECT_EQ(exc.cause().layoutId(), LayoutId::kRuntimeError); 5599} 5600 5601TEST_F(InterpreterTest, ExceptWithRightTypeCatches) { 5602 ASSERT_FALSE(runFromCStr(runtime_, R"( 5603n = 0 5604try: 5605 raise RuntimeError("whoops") 5606 n = 1 5607except RuntimeError: 5608 if n == 0: 5609 n = 2 5610)") 5611 .isError()); 5612 5613 HandleScope scope(thread_); 5614 Object n(&scope, testing::mainModuleAt(runtime_, "n")); 5615 EXPECT_TRUE(isIntEqualsWord(*n, 2)); 5616} 5617 5618TEST_F(InterpreterTest, ExceptWithRightTupleTypeCatches) { 5619 ASSERT_FALSE(runFromCStr(runtime_, R"( 5620n = 0 5621try: 5622 raise RuntimeError() 5623 n = 1 5624except (StopIteration, RuntimeError, ImportError): 5625 if n == 0: 5626 n = 2 5627)") 5628 .isError()); 5629 5630 HandleScope scope(thread_); 5631 Object n(&scope, testing::mainModuleAt(runtime_, "n")); 5632 EXPECT_TRUE(isIntEqualsWord(*n, 2)); 5633} 5634 5635TEST_F(InterpreterTest, ExceptWithWrongTypePasses) { 5636 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5637try: 5638 raise RuntimeError("something went wrong") 5639except StopIteration: 5640 pass 5641)"), 5642 LayoutId::kRuntimeError, "something went wrong")); 5643} 5644 5645TEST_F(InterpreterTest, ExceptWithWrongTupleTypePasses) { 5646 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5647try: 5648 raise RuntimeError("something went wrong") 5649except (StopIteration, ImportError): 5650 pass 5651)"), 5652 LayoutId::kRuntimeError, "something went wrong")); 5653} 5654 5655TEST_F(InterpreterTest, RaiseTypeCreatesException) { 5656 EXPECT_TRUE(raised(runFromCStr(runtime_, "raise StopIteration"), 5657 LayoutId::kStopIteration)); 5658} 5659 5660TEST_F(InterpreterTest, BareRaiseReraises) { 5661 ASSERT_FALSE(runFromCStr(runtime_, R"( 5662class MyError(Exception): 5663 pass 5664 5665inner = None 5666outer = None 5667try: 5668 try: 5669 raise MyError() 5670 except Exception as exc: 5671 inner = exc 5672 raise 5673except Exception as exc: 5674 outer = exc 5675)") 5676 .isError()); 5677 5678 HandleScope scope(thread_); 5679 Object my_error(&scope, testing::mainModuleAt(runtime_, "MyError")); 5680 EXPECT_EQ(runtime_->typeOf(*my_error), runtime_->typeAt(LayoutId::kType)); 5681 Object inner(&scope, testing::mainModuleAt(runtime_, "inner")); 5682 EXPECT_EQ(runtime_->typeOf(*inner), *my_error); 5683 Object outer(&scope, testing::mainModuleAt(runtime_, "outer")); 5684 EXPECT_EQ(*inner, *outer); 5685} 5686 5687TEST_F(InterpreterTest, ExceptWithNonExceptionTypeRaisesTypeError) { 5688 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5689try: 5690 raise RuntimeError 5691except str: 5692 pass 5693)"), 5694 LayoutId::kTypeError, 5695 "catching classes that do not inherit from " 5696 "BaseException is not allowed")); 5697} 5698 5699TEST_F(InterpreterTest, ExceptWithNonExceptionTypeInTupleRaisesTypeError) { 5700 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 5701try: 5702 raise RuntimeError 5703except (StopIteration, int, RuntimeError): 5704 pass 5705)"), 5706 LayoutId::kTypeError, 5707 "catching classes that do not inherit from " 5708 "BaseException is not allowed")); 5709} 5710 5711TEST_F(InterpreterTest, RaiseWithNoActiveExceptionRaisesRuntimeError) { 5712 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "raise\n"), 5713 LayoutId::kRuntimeError, 5714 "No active exception to reraise")); 5715} 5716 5717TEST_F(InterpreterTest, LoadAttrWithoutAttrUnwindsAttributeException) { 5718 HandleScope scope(thread_); 5719 5720 // Set up a code object that runs: {}.foo 5721 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 5722 Tuple names(&scope, runtime_->newTupleWith1(foo)); 5723 Tuple consts(&scope, runtime_->emptyTuple()); 5724 5725 // load arguments and execute the code 5726 const byte bytecode[] = {BUILD_MAP, 0, LOAD_ATTR, 0}; 5727 Code code(&scope, newCodeWithBytesConstsNames(bytecode, consts, names)); 5728 5729 // Execute the code and make sure to get the unwinded Error 5730 EXPECT_TRUE(runCode(code).isError()); 5731} 5732 5733TEST_F(InterpreterTest, ExplodeCallAcceptsList) { 5734 HandleScope scope(thread_); 5735 ASSERT_FALSE(runFromCStr(runtime_, R"( 5736def f(a, b): 5737 return [b, a] 5738 5739args = ['a', 'b'] 5740result = f(*args) 5741)") 5742 .isError()); 5743 5744 Object result(&scope, mainModuleAt(runtime_, "result")); 5745 EXPECT_PYLIST_EQ(result, {"b", "a"}); 5746} 5747 5748TEST_F(InterpreterTest, ExplodeWithIterableCalls) { 5749 HandleScope scope(thread_); 5750 EXPECT_FALSE(runFromCStr(runtime_, R"( 5751def f(a, b): 5752 return (b, a) 5753def gen(): 5754 yield 1 5755 yield 2 5756result = f(*gen()) 5757)") 5758 .isError()); 5759 5760 Object result_obj(&scope, mainModuleAt(runtime_, "result")); 5761 ASSERT_TRUE(result_obj.isTuple()); 5762 Tuple result(&scope, *result_obj); 5763 EXPECT_TRUE(isIntEqualsWord(result.at(0), 2)); 5764 EXPECT_TRUE(isIntEqualsWord(result.at(1), 1)); 5765} 5766 5767TEST_F(InterpreterTest, ForIterAnamorphicWithBuiltinIterRewritesOpcode) { 5768 HandleScope scope(thread_); 5769 ASSERT_FALSE(runFromCStr(runtime_, R"( 5770def foo(i, s=0): 5771 for a in i: 5772 s += a 5773 return s 5774 5775list_obj = [4,5] 5776dict_obj = {4: "a", 5: "b"} 5777tuple_obj = (4,5) 5778range_obj = range(4,6) 5779str_obj = "45" 5780 5781def gen(): 5782 yield 5 5783 yield 7 5784gen_obj = gen() 5785 5786class C: 5787 def __iter__(self): 5788 return D() 5789 5790class D: 5791 def __init__(self): 5792 self.used = False 5793 5794 def __next__(self): 5795 if self.used: 5796 raise StopIteration 5797 self.used = True 5798 return 400 5799 5800user_obj = C() 5801)") 5802 .isError()); 5803 Function foo(&scope, mainModuleAt(runtime_, "foo")); 5804 MutableBytes bytecode(&scope, foo.rewrittenBytecode()); 5805 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 2), FOR_ITER_ANAMORPHIC); 5806 5807 Object arg(&scope, mainModuleAt(runtime_, "list_obj")); 5808 EXPECT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, foo, arg), 9)); 5809 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 2), FOR_ITER_LIST); 5810 5811 arg = mainModuleAt(runtime_, "dict_obj"); 5812 EXPECT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, foo, arg), 9)); 5813 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 2), FOR_ITER_DICT); 5814 5815 arg = mainModuleAt(runtime_, "tuple_obj"); 5816 EXPECT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, foo, arg), 9)); 5817 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 2), FOR_ITER_TUPLE); 5818 5819 arg = mainModuleAt(runtime_, "range_obj"); 5820 EXPECT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, foo, arg), 9)); 5821 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 2), FOR_ITER_RANGE); 5822 5823 arg = mainModuleAt(runtime_, "str_obj"); 5824 Str s(&scope, runtime_->newStrFromCStr("")); 5825 EXPECT_TRUE(isStrEqualsCStr(Interpreter::call2(thread_, foo, arg, s), "45")); 5826 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 2), FOR_ITER_STR); 5827 5828 arg = mainModuleAt(runtime_, "gen_obj"); 5829 EXPECT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, foo, arg), 12)); 5830 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 2), FOR_ITER_GENERATOR); 5831 5832 // Resetting the opcode. 5833 arg = mainModuleAt(runtime_, "user_obj"); 5834 EXPECT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, foo, arg), 400)); 5835 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 2), FOR_ITER_MONOMORPHIC); 5836} 5837 5838TEST_F(InterpreterTest, FormatValueCallsDunderStr) { 5839 HandleScope scope(thread_); 5840 ASSERT_FALSE(runFromCStr(runtime_, R"( 5841class C: 5842 def __str__(self): 5843 return "foobar" 5844result = f"{C()!s}" 5845)") 5846 .isError()); 5847 Object result(&scope, mainModuleAt(runtime_, "result")); 5848 EXPECT_TRUE(isStrEqualsCStr(*result, "foobar")); 5849} 5850 5851TEST_F(InterpreterTest, FormatValueFallsBackToDunderRepr) { 5852 HandleScope scope(thread_); 5853 ASSERT_FALSE(runFromCStr(runtime_, R"( 5854class C: 5855 def __repr__(self): 5856 return "foobar" 5857result = f"{C()!s}" 5858)") 5859 .isError()); 5860 Object result(&scope, mainModuleAt(runtime_, "result")); 5861 EXPECT_TRUE(isStrEqualsCStr(*result, "foobar")); 5862} 5863 5864TEST_F(InterpreterTest, FormatValueCallsDunderRepr) { 5865 HandleScope scope(thread_); 5866 ASSERT_FALSE(runFromCStr(runtime_, R"( 5867class C: 5868 def __repr__(self): 5869 return "foobar" 5870result = f"{C()!r}" 5871)") 5872 .isError()); 5873 Object result(&scope, mainModuleAt(runtime_, "result")); 5874 EXPECT_TRUE(isStrEqualsCStr(*result, "foobar")); 5875} 5876 5877TEST_F(InterpreterTest, FormatValueAsciiCallsDunderRepr) { 5878 HandleScope scope(thread_); 5879 ASSERT_FALSE(runFromCStr(runtime_, R"( 5880class C: 5881 def __repr__(self): 5882 return "foobar" 5883result = f"{C()!a}" 5884)") 5885 .isError()); 5886 Object result(&scope, mainModuleAt(runtime_, "result")); 5887 EXPECT_TRUE(isStrEqualsCStr(*result, "foobar")); 5888} 5889 5890TEST_F(InterpreterTest, BreakInTryBreaks) { 5891 HandleScope scope(thread_); 5892 ASSERT_FALSE(runFromCStr(runtime_, R"( 5893result = 0 5894for i in range(5): 5895 try: 5896 break 5897 except: 5898 pass 5899result = 10 5900)") 5901 .isError()); 5902 Object result(&scope, mainModuleAt(runtime_, "result")); 5903 EXPECT_TRUE(isIntEqualsWord(*result, 10)); 5904} 5905 5906TEST_F(InterpreterTest, ContinueInExceptContinues) { 5907 HandleScope scope(thread_); 5908 ASSERT_FALSE(runFromCStr(runtime_, R"( 5909result = 0 5910for i in range(5): 5911 try: 5912 if i == 3: 5913 raise RuntimeError() 5914 except: 5915 result += i 5916 continue 5917 result -= i 5918)") 5919 .isError()); 5920 Object result(&scope, mainModuleAt(runtime_, "result")); 5921 EXPECT_TRUE(isIntEqualsWord(*result, -4)); 5922} 5923 5924TEST_F(InterpreterTest, RaiseInLoopRaisesRuntimeError) { 5925 HandleScope scope(thread_); 5926 ASSERT_FALSE(runFromCStr(runtime_, R"( 5927result = 0 5928try: 5929 for i in range(5): 5930 result += i 5931 if i == 2: 5932 raise RuntimeError() 5933 result += 100 5934except: 5935 result += 1000 5936)") 5937 .isError()); 5938 Object result(&scope, mainModuleAt(runtime_, "result")); 5939 EXPECT_TRUE(isIntEqualsWord(*result, 1003)); 5940} 5941 5942TEST_F(InterpreterTest, ReturnInsideTryRunsFinally) { 5943 HandleScope scope(thread_); 5944 ASSERT_FALSE(runFromCStr(runtime_, R"( 5945ran_finally = False 5946 5947def f(): 5948 try: 5949 return 56789 5950 finally: 5951 global ran_finally 5952 ran_finally = True 5953 5954result = f() 5955)") 5956 .isError()); 5957 Object result(&scope, mainModuleAt(runtime_, "result")); 5958 EXPECT_TRUE(isIntEqualsWord(*result, 56789)); 5959 5960 Object ran_finally(&scope, mainModuleAt(runtime_, "ran_finally")); 5961 EXPECT_EQ(*ran_finally, Bool::trueObj()); 5962} 5963 5964TEST_F(InterpreterTest, ReturnInsideFinallyOverridesEarlierReturn) { 5965 HandleScope scope(thread_); 5966 ASSERT_FALSE(runFromCStr(runtime_, R"( 5967def f(): 5968 try: 5969 return 123 5970 finally: 5971 return 456 5972 5973result = f() 5974)") 5975 .isError()); 5976 Object result(&scope, mainModuleAt(runtime_, "result")); 5977 EXPECT_TRUE(isIntEqualsWord(*result, 456)); 5978} 5979 5980TEST_F(InterpreterTest, ReturnInsideWithRunsDunderExit) { 5981 HandleScope scope(thread_); 5982 ASSERT_FALSE(runFromCStr(runtime_, R"( 5983sequence = "" 5984 5985class Mgr: 5986 def __enter__(self): 5987 global sequence 5988 sequence += "enter " 5989 def __exit__(self, exc, value, tb): 5990 global sequence 5991 sequence += "exit" 5992 5993def foo(): 5994 with Mgr(): 5995 global sequence 5996 sequence += "in foo " 5997 return 1234 5998 5999result = foo() 6000)") 6001 .isError()); 6002 Object result(&scope, mainModuleAt(runtime_, "result")); 6003 EXPECT_TRUE(isIntEqualsWord(*result, 1234)); 6004 6005 Object sequence(&scope, mainModuleAt(runtime_, "sequence")); 6006 EXPECT_TRUE(isStrEqualsCStr(*sequence, "enter in foo exit")); 6007} 6008 6009TEST_F(InterpreterTest, 6010 WithStatementWithManagerWithoutEnterRaisesAttributeError) { 6011 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 6012with None: 6013 pass 6014)"), 6015 LayoutId::kAttributeError, "__enter__")); 6016} 6017 6018TEST_F(InterpreterTest, 6019 WithStatementWithManagerWithoutExitRaisesAttributeError) { 6020 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 6021class C: 6022 def __enter__(self): 6023 pass 6024with C(): 6025 pass 6026)"), 6027 LayoutId::kAttributeError, "__exit__")); 6028} 6029 6030TEST_F(InterpreterTest, 6031 WithStatementWithManagerEnterRaisingPropagatesException) { 6032 EXPECT_TRUE(raised(runFromCStr(runtime_, R"( 6033class C: 6034 def __enter__(self): 6035 raise UserWarning('') 6036 def __exit__(self, *args): 6037 pass 6038with C(): 6039 pass 6040)"), 6041 LayoutId::kUserWarning)); 6042} 6043 6044TEST_F(InterpreterTest, WithStatementPropagatesException) { 6045 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 6046class Mgr: 6047 def __enter__(self): 6048 pass 6049 def __exit__(self, exc, value, tb): 6050 return () 6051 6052def raises(): 6053 raise RuntimeError("It's dead, Jim") 6054 6055with Mgr(): 6056 raises() 6057)"), 6058 LayoutId::kRuntimeError, "It's dead, Jim")); 6059} 6060 6061TEST_F(InterpreterTest, WithStatementPassesCorrectExceptionToExit) { 6062 HandleScope scope(thread_); 6063 EXPECT_TRUE(raised(runFromCStr(runtime_, R"( 6064raised_exc = None 6065exit_info = None 6066 6067class Mgr: 6068 def __enter__(self): 6069 pass 6070 def __exit__(self, exc, value, tb): 6071 global exit_info 6072 exit_info = (exc, value, tb) 6073 6074def raises(): 6075 global raised_exc 6076 raised_exc = StopIteration("nope") 6077 raise raised_exc 6078 6079with Mgr(): 6080 raises() 6081)"), 6082 LayoutId::kStopIteration)); 6083 Object exit_info(&scope, mainModuleAt(runtime_, "exit_info")); 6084 ASSERT_TRUE(exit_info.isTuple()); 6085 Tuple tuple(&scope, *exit_info); 6086 ASSERT_EQ(tuple.length(), 3); 6087 EXPECT_EQ(tuple.at(0), runtime_->typeAt(LayoutId::kStopIteration)); 6088 6089 Object raised_exc(&scope, mainModuleAt(runtime_, "raised_exc")); 6090 EXPECT_EQ(tuple.at(1), *raised_exc); 6091 6092 // TODO(bsimmers): Check traceback once we record them. 6093} 6094 6095TEST_F(InterpreterTest, WithStatementSwallowsException) { 6096 HandleScope scope(thread_); 6097 EXPECT_FALSE(runFromCStr(runtime_, R"( 6098class Mgr: 6099 def __enter__(self): 6100 pass 6101 def __exit__(self, exc, value, tb): 6102 return 1 6103 6104def raises(): 6105 raise RuntimeError() 6106 6107with Mgr(): 6108 raises() 6109result = 1234 6110)") 6111 .isError()); 6112 6113 Object result(&scope, mainModuleAt(runtime_, "result")); 6114 EXPECT_TRUE(isIntEqualsWord(*result, 1234)); 6115} 6116 6117TEST_F(InterpreterTest, WithStatementWithRaisingExitRaises) { 6118 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 6119class Mgr: 6120 def __enter__(self): 6121 pass 6122 def __exit__(self, exc, value, tb): 6123 raise RuntimeError("from exit") 6124 6125def raises(): 6126 raise RuntimeError("from raises") 6127 6128with Mgr(): 6129 raises() 6130)"), 6131 LayoutId::kRuntimeError, "from exit")); 6132 6133 // TODO(T40269344): Inspect __context__ from the raised exception. 6134} 6135 6136TEST_F(InterpreterTest, LoadNameReturnsSameResultAsCahedValueFromLoadGlobal) { 6137 EXPECT_FALSE(runFromCStr(runtime_, R"( 6138t = 400 6139 6140def update_t(): 6141 global t 6142 t = 500 6143 6144def get_t(): 6145 global t 6146 return t 6147 6148update_t() 6149load_name_t = t 6150load_global_t = get_t() 6151)") 6152 .isError()); 6153 EXPECT_EQ(mainModuleAt(runtime_, "load_name_t"), 6154 mainModuleAt(runtime_, "load_global_t")); 6155} 6156 6157TEST_F(InterpreterTest, LoadGlobalCachedReturnsModuleDictValue) { 6158 HandleScope scope(thread_); 6159 EXPECT_FALSE(runFromCStr(runtime_, R"( 6160a = 400 6161 6162def foo(): 6163 return a + a 6164 6165result = foo() 6166)") 6167 .isError()); 6168 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 800)); 6169 Function function(&scope, mainModuleAt(runtime_, "foo")); 6170 ASSERT_TRUE(isStrEqualsCStr( 6171 Tuple::cast(Code::cast(function.code()).names()).at(0), "a")); 6172 MutableTuple caches(&scope, function.caches()); 6173 EXPECT_TRUE( 6174 isIntEqualsWord(valueCellValue(icLookupGlobalVar(*caches, 0)), 400)); 6175} 6176 6177TEST_F(InterpreterTest, 6178 LoadGlobalCachedReturnsBuiltinDictValueAndSetsPlaceholder) { 6179 HandleScope scope(thread_); 6180 EXPECT_FALSE(runFromCStr(runtime_, R"( 6181__builtins__.a = 400 6182 6183def foo(): 6184 return a + a 6185 6186result = foo() 6187)") 6188 .isError()); 6189 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 800)); 6190 Function function(&scope, mainModuleAt(runtime_, "foo")); 6191 ASSERT_TRUE(isStrEqualsCStr( 6192 Tuple::cast(Code::cast(function.code()).names()).at(0), "a")); 6193 MutableTuple caches(&scope, function.caches()); 6194 EXPECT_TRUE( 6195 isIntEqualsWord(valueCellValue(icLookupGlobalVar(*caches, 0)), 400)); 6196 6197 Module module(&scope, function.moduleObject()); 6198 Object name(&scope, Runtime::internStrFromCStr(thread_, "a")); 6199 RawObject module_entry = NoneType::object(); 6200 EXPECT_TRUE(attributeValueCellAt(*module, *name, &module_entry)); 6201 ASSERT_TRUE(module_entry.isValueCell()); 6202 EXPECT_TRUE(ValueCell::cast(module_entry).isPlaceholder()); 6203} 6204 6205TEST_F(InterpreterTest, StoreGlobalCachedInvalidatesCachedBuiltinToBeShadowed) { 6206 HandleScope scope(thread_); 6207 EXPECT_FALSE(runFromCStr(runtime_, R"( 6208__builtins__.a = 400 6209 6210def foo(): 6211 return a + a 6212 6213def bar(): 6214 # Shadowing `__builtins__.a`. 6215 global a 6216 a = 123 6217 6218foo() 6219bar() 6220)") 6221 .isError()); 6222 Function function(&scope, mainModuleAt(runtime_, "foo")); 6223 ASSERT_TRUE(isStrEqualsCStr( 6224 Tuple::cast(Code::cast(function.code()).names()).at(0), "a")); 6225 MutableTuple caches(&scope, function.caches()); 6226 EXPECT_TRUE(icLookupGlobalVar(*caches, 0).isNoneType()); 6227} 6228 6229TEST_F(InterpreterTest, DeleteGlobalInvalidatesCachedValue) { 6230 HandleScope scope(thread_); 6231 EXPECT_FALSE(runFromCStr(runtime_, R"( 6232a = 400 6233def foo(): 6234 return a + a 6235 6236def bar(): 6237 global a 6238 del a 6239 6240foo() 6241bar() 6242)") 6243 .isError()); 6244 Function function(&scope, mainModuleAt(runtime_, "foo")); 6245 ASSERT_TRUE(isStrEqualsCStr( 6246 Tuple::cast(Code::cast(function.code()).names()).at(0), "a")); 6247 MutableTuple caches(&scope, function.caches()); 6248 EXPECT_TRUE(icLookupGlobalVar(*caches, 0).isNoneType()); 6249} 6250 6251TEST_F(InterpreterTest, StoreNameInvalidatesCachedBuiltinToBeShadowed) { 6252 HandleScope scope(thread_); 6253 EXPECT_FALSE(runFromCStr(runtime_, R"( 6254__builtins__.a = 400 6255 6256def foo(): 6257 return a + a 6258 6259foo() 6260a = 800 6261)") 6262 .isError()); 6263 Function function(&scope, mainModuleAt(runtime_, "foo")); 6264 ASSERT_TRUE(isStrEqualsCStr( 6265 Tuple::cast(Code::cast(function.code()).names()).at(0), "a")); 6266 MutableTuple caches(&scope, function.caches()); 6267 EXPECT_TRUE(icLookupGlobalVar(*caches, 0).isNoneType()); 6268} 6269 6270TEST_F(InterpreterTest, DeleteNameInvalidatesCachedGlobalVar) { 6271 HandleScope scope(thread_); 6272 EXPECT_FALSE(runFromCStr(runtime_, R"( 6273a = 400 6274def foo(): 6275 return a + a 6276 6277foo() 6278del a 6279)") 6280 .isError()); 6281 Function function(&scope, mainModuleAt(runtime_, "foo")); 6282 ASSERT_TRUE(isStrEqualsCStr( 6283 Tuple::cast(Code::cast(function.code()).names()).at(0), "a")); 6284 MutableTuple caches(&scope, function.caches()); 6285 EXPECT_TRUE(icLookupGlobalVar(*caches, 0).isNoneType()); 6286} 6287 6288TEST_F( 6289 InterpreterTest, 6290 StoreAttrCachedInvalidatesInstanceOffsetCachesByAssigningTypeDescriptor) { 6291 HandleScope scope(thread_); 6292 EXPECT_FALSE(runFromCStr(runtime_, R"( 6293class C: 6294 def __init__(self): 6295 self.foo = 400 6296 6297def get_foo(c): 6298 return c.foo 6299 6300def do_not_invalidate0(): 6301 C.bar = property (lambda self: "data descriptor in a different attr") 6302 6303def do_not_invalidate1(): 6304 C.foo = 9999 6305 6306def invalidate(): 6307 C.foo = property (lambda self: "data descriptor") 6308 6309c = C() 6310)") 6311 .isError()); 6312 Object c(&scope, mainModuleAt(runtime_, "c")); 6313 Function get_foo(&scope, mainModuleAt(runtime_, "get_foo")); 6314 Function do_not_invalidate0(&scope, 6315 mainModuleAt(runtime_, "do_not_invalidate0")); 6316 Function do_not_invalidate1(&scope, 6317 mainModuleAt(runtime_, "do_not_invalidate1")); 6318 Function invalidate(&scope, mainModuleAt(runtime_, "invalidate")); 6319 MutableTuple caches(&scope, get_foo.caches()); 6320 // Load the cache 6321 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 6322 ASSERT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, get_foo, c), 400)); 6323 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isSmallInt()); 6324 6325 // Assign a data descriptor to a different attribute name. 6326 ASSERT_TRUE(Interpreter::call0(thread_, do_not_invalidate0).isNoneType()); 6327 EXPECT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isSmallInt()); 6328 6329 // Assign a non-data descriptor to the cache's attribute name. 6330 ASSERT_TRUE(Interpreter::call0(thread_, do_not_invalidate1).isNoneType()); 6331 EXPECT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isSmallInt()); 6332 6333 // Assign a data descriptor the cache's attribute name that actually causes 6334 // invalidation. 6335 ASSERT_TRUE(Interpreter::call0(thread_, invalidate).isNoneType()); 6336 // Verify that the cache is empty and calling get_foo() returns a fresh value. 6337 EXPECT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 6338 EXPECT_TRUE(isStrEqualsCStr(Interpreter::call1(thread_, get_foo, c), 6339 "data descriptor")); 6340} 6341 6342TEST_F(InterpreterTest, 6343 StoreAttrCachedInvalidatesTypeAttrCachesByUpdatingTypeAttribute) { 6344 HandleScope scope(thread_); 6345 EXPECT_FALSE(runFromCStr(runtime_, R"( 6346class C: 6347 def foo(self): 6348 return 400; 6349 6350def call_foo(c): 6351 return c.foo() 6352 6353def do_not_invalidate(): 6354 C.bar = lambda c: "new type attr" 6355 6356def invalidate(): 6357 C.foo = lambda c: "new type attr" 6358 6359old_foo = C.foo 6360c = C() 6361)") 6362 .isError()); 6363 Object c(&scope, mainModuleAt(runtime_, "c")); 6364 Function old_foo(&scope, mainModuleAt(runtime_, "old_foo")); 6365 Function call_foo(&scope, mainModuleAt(runtime_, "call_foo")); 6366 Function do_not_invalidate(&scope, 6367 mainModuleAt(runtime_, "do_not_invalidate")); 6368 Function invalidate(&scope, mainModuleAt(runtime_, "invalidate")); 6369 MutableTuple caches(&scope, call_foo.caches()); 6370 // Load the cache 6371 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 6372 ASSERT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, call_foo, c), 400)); 6373 ASSERT_EQ(icLookupAttr(*caches, 1, c.layoutId()), *old_foo); 6374 6375 // Assign a non-data descriptor to different attribute name. 6376 ASSERT_TRUE(Interpreter::call0(thread_, do_not_invalidate).isNoneType()); 6377 ASSERT_EQ(icLookupAttr(*caches, 1, c.layoutId()), *old_foo); 6378 6379 // Invalidate the cache. 6380 ASSERT_TRUE(Interpreter::call0(thread_, invalidate).isNoneType()); 6381 // Verify that the cache is empty and calling get_foo() returns a fresh value. 6382 EXPECT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 6383 EXPECT_TRUE(isStrEqualsCStr(Interpreter::call1(thread_, call_foo, c), 6384 "new type attr")); 6385} 6386 6387TEST_F( 6388 InterpreterTest, 6389 StoreAttrCachedInvalidatesAttributeCachesByUpdatingMatchingTypeAttributesOfSuperclass) { 6390 HandleScope scope(thread_); 6391 EXPECT_FALSE(runFromCStr(runtime_, R"( 6392class B: 6393 pass 6394 6395class C(B): 6396 def __init__(self): 6397 self.foo = 400 6398 6399class D(C): 6400 pass 6401 6402def get_foo(c): 6403 return c.foo 6404 6405def do_not_invalidate(): 6406 D.foo = property (lambda self: "data descriptor") 6407 6408def invalidate(): 6409 B.foo = property (lambda self: "data descriptor") 6410 6411c = C() 6412)") 6413 .isError()); 6414 Type type_b(&scope, mainModuleAt(runtime_, "B")); 6415 Type type_c(&scope, mainModuleAt(runtime_, "C")); 6416 Object c(&scope, mainModuleAt(runtime_, "c")); 6417 Function get_foo(&scope, mainModuleAt(runtime_, "get_foo")); 6418 Function do_not_invalidate(&scope, 6419 mainModuleAt(runtime_, "do_not_invalidate")); 6420 Function invalidate(&scope, mainModuleAt(runtime_, "invalidate")); 6421 MutableTuple caches(&scope, get_foo.caches()); 6422 // Load the cache. 6423 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 6424 ASSERT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, get_foo, c), 400)); 6425 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isSmallInt()); 6426 6427 // Updating a subclass' type attribute doesn't invalidate the cache. 6428 ASSERT_TRUE(Interpreter::call0(thread_, do_not_invalidate).isNoneType()); 6429 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isSmallInt()); 6430 6431 // Verify that all type dictionaries in C's mro have dependentices to get_foo. 6432 Object foo_name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 6433 Object result(&scope, typeValueCellAt(*type_b, *foo_name)); 6434 ASSERT_TRUE(result.isValueCell()); 6435 ASSERT_TRUE(ValueCell::cast(*result).dependencyLink().isWeakLink()); 6436 EXPECT_EQ( 6437 WeakLink::cast(ValueCell::cast(*result).dependencyLink()).referent(), 6438 *get_foo); 6439 6440 result = typeValueCellAt(*type_c, *foo_name); 6441 ASSERT_TRUE(result.isValueCell()); 6442 ASSERT_TRUE(ValueCell::cast(*result).dependencyLink().isWeakLink()); 6443 EXPECT_EQ( 6444 WeakLink::cast(ValueCell::cast(*result).dependencyLink()).referent(), 6445 *get_foo); 6446 6447 // Invalidate the cache. 6448 ASSERT_TRUE(Interpreter::call0(thread_, invalidate).isNoneType()); 6449 // Verify that the cache is empty and calling get_foo() returns a fresh value. 6450 EXPECT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 6451 EXPECT_TRUE(isStrEqualsCStr(Interpreter::call1(thread_, get_foo, c), 6452 "data descriptor")); 6453} 6454 6455TEST_F(InterpreterTest, StoreAttrCachedInvalidatesBinaryOpCaches) { 6456 HandleScope scope(thread_); 6457 EXPECT_FALSE(runFromCStr(runtime_, R"( 6458def cache_A_add(a, b): 6459 return a + b 6460 6461class A: 6462 def __add__(self, other): return "A.__add__" 6463 6464class B: 6465 pass 6466 6467def update_A_add(): 6468 A.__add__ = lambda self, other: "new A.__add__" 6469 6470a = A() 6471b = B() 6472 6473A_add = A.__add__ 6474 6475cache_A_add(a, b) 6476)") 6477 .isError()); 6478 Object a(&scope, mainModuleAt(runtime_, "a")); 6479 Object b(&scope, mainModuleAt(runtime_, "b")); 6480 Object a_add(&scope, mainModuleAt(runtime_, "A_add")); 6481 6482 Function cache_a_add(&scope, mainModuleAt(runtime_, "cache_A_add")); 6483 BinaryOpFlags flags_out; 6484 // Ensure that A.__add__ is cached in cache_A_add. 6485 Object cached_in_cache_a_add( 6486 &scope, icLookupBinaryOp(MutableTuple::cast(cache_a_add.caches()), 0, 6487 a.layoutId(), b.layoutId(), &flags_out)); 6488 ASSERT_EQ(cached_in_cache_a_add, *a_add); 6489 6490 // Ensure that cache_a_add is being tracked as a dependent from A.__add__. 6491 Type type_a(&scope, mainModuleAt(runtime_, "A")); 6492 Str dunder_add(&scope, runtime_->symbols()->at(ID(__add__))); 6493 ValueCell a_add_value_cell(&scope, typeValueCellAt(*type_a, *dunder_add)); 6494 ASSERT_FALSE(a_add_value_cell.isPlaceholder()); 6495 EXPECT_EQ(WeakLink::cast(a_add_value_cell.dependencyLink()).referent(), 6496 *cache_a_add); 6497 6498 // Ensure that cache_a_add is being tracked as a dependent from B.__radd__. 6499 Type type_b(&scope, mainModuleAt(runtime_, "B")); 6500 Str dunder_radd(&scope, runtime_->symbols()->at(ID(__radd__))); 6501 ValueCell b_radd_value_cell(&scope, typeValueCellAt(*type_b, *dunder_radd)); 6502 ASSERT_TRUE(b_radd_value_cell.isPlaceholder()); 6503 EXPECT_EQ(WeakLink::cast(b_radd_value_cell.dependencyLink()).referent(), 6504 *cache_a_add); 6505 6506 // Updating A.__add__ invalidates the cache. 6507 Function invalidate(&scope, mainModuleAt(runtime_, "update_A_add")); 6508 ASSERT_TRUE(Interpreter::call0(thread_, invalidate).isNoneType()); 6509 // Verify that the cache is evicted. 6510 EXPECT_TRUE(icLookupBinaryOp(MutableTuple::cast(cache_a_add.caches()), 0, 6511 a.layoutId(), b.layoutId(), &flags_out) 6512 .isErrorNotFound()); 6513 // Verify that the dependencies are deleted. 6514 EXPECT_TRUE(a_add_value_cell.dependencyLink().isNoneType()); 6515 EXPECT_TRUE(b_radd_value_cell.dependencyLink().isNoneType()); 6516} 6517 6518TEST_F(InterpreterTest, StoreAttrCachedInvalidatesCompareOpTypeAttrCaches) { 6519 HandleScope scope(thread_); 6520 EXPECT_FALSE(runFromCStr(runtime_, R"( 6521def cache_compare_op(a, b): 6522 return a >= b 6523 6524class A: 6525 def __le__(self, other): return True 6526 6527 def __ge__(self, other): return True 6528 6529class B: 6530 def __le__(self, other): return True 6531 6532 def __ge__(self, other): return True 6533 6534def do_not_invalidate(): 6535 A.__le__ = lambda self, other: False 6536 B.__ge__ = lambda self, other: False 6537 6538def invalidate(): 6539 A.__ge__ = lambda self, other: False 6540 6541a = A() 6542b = B() 6543A__ge__ = A.__ge__ 6544c = cache_compare_op(a, b) 6545)") 6546 .isError()); 6547 Object a(&scope, mainModuleAt(runtime_, "a")); 6548 Object b(&scope, mainModuleAt(runtime_, "b")); 6549 Object type_a__dunder_ge(&scope, mainModuleAt(runtime_, "A__ge__")); 6550 6551 // Ensure that A.__ge__ is cached. 6552 Function cache_compare_op(&scope, mainModuleAt(runtime_, "cache_compare_op")); 6553 MutableTuple caches(&scope, cache_compare_op.caches()); 6554 BinaryOpFlags flags_out; 6555 Object cached(&scope, icLookupBinaryOp(*caches, 0, a.layoutId(), b.layoutId(), 6556 &flags_out)); 6557 ASSERT_EQ(*cached, *type_a__dunder_ge); 6558 6559 // Updating irrelevant compare op dunder functions doesn't trigger 6560 // invalidation. 6561 Function do_not_invalidate(&scope, 6562 mainModuleAt(runtime_, "do_not_invalidate")); 6563 ASSERT_TRUE(Interpreter::call0(thread_, do_not_invalidate).isNoneType()); 6564 cached = icLookupBinaryOp(*caches, 0, a.layoutId(), b.layoutId(), &flags_out); 6565 EXPECT_EQ(*cached, *type_a__dunder_ge); 6566 6567 // Updating relevant compare op dunder functions triggers invalidation. 6568 Function invalidate(&scope, mainModuleAt(runtime_, "invalidate")); 6569 ASSERT_TRUE(Interpreter::call0(thread_, invalidate).isNoneType()); 6570 ASSERT_TRUE( 6571 icLookupBinaryOp(*caches, 0, a.layoutId(), b.layoutId(), &flags_out) 6572 .isErrorNotFound()); 6573} 6574 6575TEST_F(InterpreterTest, StoreAttrCachedInvalidatesInplaceOpCaches) { 6576 HandleScope scope(thread_); 6577 EXPECT_FALSE(runFromCStr(runtime_, R"( 6578def cache_A_iadd(a, b): 6579 a += b 6580 6581class A: 6582 def __iadd__(self, other): return "A.__iadd__" 6583 6584class B: 6585 pass 6586 6587def update_A_iadd(): 6588 A.__iadd__ = lambda self, other: "new A.__add__" 6589 6590a = A() 6591b = B() 6592 6593A_iadd = A.__iadd__ 6594 6595cache_A_iadd(a, b) 6596)") 6597 .isError()); 6598 Object a(&scope, mainModuleAt(runtime_, "a")); 6599 Object b(&scope, mainModuleAt(runtime_, "b")); 6600 Object a_iadd(&scope, mainModuleAt(runtime_, "A_iadd")); 6601 6602 Function cache_a_iadd(&scope, mainModuleAt(runtime_, "cache_A_iadd")); 6603 BinaryOpFlags flags_out; 6604 // Ensure that A.__iadd__ is cached in cache_A_iadd. 6605 Object cached_in_cache_a_iadd( 6606 &scope, icLookupBinaryOp(MutableTuple::cast(cache_a_iadd.caches()), 0, 6607 a.layoutId(), b.layoutId(), &flags_out)); 6608 ASSERT_EQ(cached_in_cache_a_iadd, *a_iadd); 6609 6610 // Ensure that cache_a_iadd is being tracked as a dependent from A.__iadd__. 6611 Type type_a(&scope, mainModuleAt(runtime_, "A")); 6612 Str dunder_iadd(&scope, runtime_->symbols()->at(ID(__iadd__))); 6613 ValueCell a_iadd_value_cell(&scope, typeValueCellAt(*type_a, *dunder_iadd)); 6614 ASSERT_FALSE(a_iadd_value_cell.isPlaceholder()); 6615 EXPECT_EQ(WeakLink::cast(a_iadd_value_cell.dependencyLink()).referent(), 6616 *cache_a_iadd); 6617 6618 Str dunder_add(&scope, runtime_->symbols()->at(ID(__add__))); 6619 ValueCell a_add_value_cell(&scope, typeValueCellAt(*type_a, *dunder_add)); 6620 ASSERT_TRUE(a_add_value_cell.isPlaceholder()); 6621 EXPECT_EQ(WeakLink::cast(a_add_value_cell.dependencyLink()).referent(), 6622 *cache_a_iadd); 6623 6624 // Ensure that cache_a_iadd is being tracked as a dependent from B.__riadd__. 6625 Type type_b(&scope, mainModuleAt(runtime_, "B")); 6626 Str dunder_radd(&scope, runtime_->symbols()->at(ID(__radd__))); 6627 ValueCell b_radd_value_cell(&scope, typeValueCellAt(*type_b, *dunder_radd)); 6628 ASSERT_TRUE(b_radd_value_cell.isPlaceholder()); 6629 EXPECT_EQ(WeakLink::cast(b_radd_value_cell.dependencyLink()).referent(), 6630 *cache_a_iadd); 6631 6632 // Updating A.__iadd__ invalidates the cache. 6633 Function invalidate(&scope, mainModuleAt(runtime_, "update_A_iadd")); 6634 ASSERT_TRUE(Interpreter::call0(thread_, invalidate).isNoneType()); 6635 // Verify that the cache is evicted. 6636 EXPECT_TRUE(icLookupBinaryOp(MutableTuple::cast(cache_a_iadd.caches()), 0, 6637 a.layoutId(), b.layoutId(), &flags_out) 6638 .isErrorNotFound()); 6639 // Verify that the dependencies are deleted. 6640 EXPECT_TRUE(a_iadd_value_cell.dependencyLink().isNoneType()); 6641 EXPECT_TRUE(a_add_value_cell.dependencyLink().isNoneType()); 6642 EXPECT_TRUE(b_radd_value_cell.dependencyLink().isNoneType()); 6643} 6644 6645TEST_F(InterpreterTest, LoadMethodLoadingMethodFollowedByCallMethod) { 6646 HandleScope scope(thread_); 6647 EXPECT_FALSE(runFromCStr(runtime_, R"( 6648class C: 6649 def __init__(self): 6650 self.val = 40 6651 6652 def compute(self, arg0, arg1): 6653 return self.val + arg0 + arg1 6654 6655def test(): 6656 return c.compute(10, 20) 6657 6658c = C() 6659)") 6660 .isError()); 6661 Function test_function(&scope, mainModuleAt(runtime_, "test")); 6662 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 6663 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6664 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 4), CALL_METHOD); 6665 6666 EXPECT_TRUE(isIntEqualsWord(Interpreter::call0(thread_, test_function), 70)); 6667} 6668 6669TEST_F(InterpreterTest, LoadMethodInitDoesNotCacheInstanceAttributes) { 6670 HandleScope scope(thread_); 6671 EXPECT_FALSE(runFromCStr(runtime_, R"( 6672class C: 6673 def __init__(self): 6674 self.val = 40 6675 6676def foo(a, b): return a + b 6677c = C() 6678c.compute = foo 6679def test(): 6680 return c.compute(10, 20) 6681)") 6682 .isError()); 6683 Function test_function(&scope, mainModuleAt(runtime_, "test")); 6684 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 6685 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6686 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 4), CALL_METHOD); 6687 6688 Object c(&scope, mainModuleAt(runtime_, "c")); 6689 LayoutId layout_id = c.layoutId(); 6690 MutableTuple caches(&scope, test_function.caches()); 6691 // Cache miss. 6692 ASSERT_TRUE( 6693 icLookupAttr(*caches, rewrittenBytecodeArgAt(bytecode, 1), layout_id) 6694 .isErrorNotFound()); 6695 EXPECT_TRUE(isIntEqualsWord(Interpreter::call0(thread_, test_function), 30)); 6696 6697 // Still cache miss. 6698 ASSERT_TRUE( 6699 icLookupAttr(*caches, rewrittenBytecodeArgAt(bytecode, 1), layout_id) 6700 .isErrorNotFound()); 6701} 6702 6703TEST_F(InterpreterTest, LoadMethodCachedCachingFunctionFollowedByCallMethod) { 6704 HandleScope scope(thread_); 6705 EXPECT_FALSE(runFromCStr(runtime_, R"( 6706class C: 6707 def __init__(self): 6708 self.val = 40 6709 6710 def compute(self, arg0, arg1): 6711 return self.val + arg0 + arg1 6712 6713def test(): 6714 return c.compute(10, 20) 6715 6716c = C() 6717)") 6718 .isError()); 6719 Function test_function(&scope, mainModuleAt(runtime_, "test")); 6720 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 6721 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6722 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 4), CALL_METHOD); 6723 6724 // Cache miss. 6725 Object c(&scope, mainModuleAt(runtime_, "c")); 6726 LayoutId layout_id = c.layoutId(); 6727 MutableTuple caches(&scope, test_function.caches()); 6728 ASSERT_TRUE( 6729 icLookupAttr(*caches, rewrittenBytecodeArgAt(bytecode, 1), layout_id) 6730 .isErrorNotFound()); 6731 EXPECT_TRUE(isIntEqualsWord(Interpreter::call0(thread_, test_function), 70)); 6732 6733 // Cache hit. 6734 ASSERT_TRUE( 6735 icLookupAttr(*caches, rewrittenBytecodeArgAt(bytecode, 1), layout_id) 6736 .isFunction()); 6737 EXPECT_TRUE(isIntEqualsWord(Interpreter::call0(thread_, test_function), 70)); 6738} 6739 6740TEST_F(InterpreterTest, LoadMethodCachedModuleFunction) { 6741 EXPECT_FALSE(runFromCStr(runtime_, R"( 6742import sys 6743 6744class C: 6745 def getdefaultencoding(self): 6746 return "no-utf8" 6747 6748def test(obj): 6749 return obj.getdefaultencoding() 6750 6751cached = sys.getdefaultencoding 6752obj = C() 6753)") 6754 .isError()); 6755 HandleScope scope(thread_); 6756 Function test_function(&scope, mainModuleAt(runtime_, "test")); 6757 Function expected_value(&scope, mainModuleAt(runtime_, "cached")); 6758 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 6759 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6760 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 2), CALL_METHOD); 6761 6762 // Cache miss. 6763 Module sys_module(&scope, runtime_->findModuleById(ID(sys))); 6764 MutableTuple caches(&scope, test_function.caches()); 6765 word cache_index = 6766 rewrittenBytecodeCacheAt(bytecode, 1) * kIcPointersPerEntry; 6767 Object key(&scope, caches.at(cache_index + kIcEntryKeyOffset)); 6768 EXPECT_EQ(*key, NoneType::object()); 6769 6770 // Call. 6771 EXPECT_TRUE(isStrEqualsCStr( 6772 Interpreter::call1(thread_, test_function, sys_module), "utf-8")); 6773 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_MODULE); 6774 6775 // Cache hit. 6776 key = caches.at(cache_index + kIcEntryKeyOffset); 6777 EXPECT_TRUE(isIntEqualsWord(*key, sys_module.id())); 6778 Object value(&scope, caches.at(cache_index + kIcEntryValueOffset)); 6779 ASSERT_TRUE(value.isValueCell()); 6780 EXPECT_EQ(ValueCell::cast(*value).value(), *expected_value); 6781 6782 // Call. 6783 EXPECT_TRUE(isStrEqualsCStr( 6784 Interpreter::call1(thread_, test_function, sys_module), "utf-8")); 6785 6786 // Rewrite. 6787 Object obj(&scope, mainModuleAt(runtime_, "obj")); 6788 EXPECT_TRUE(isStrEqualsCStr(Interpreter::call1(thread_, test_function, obj), 6789 "no-utf8")); 6790 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_INSTANCE_FUNCTION); 6791 key = caches.at(cache_index + kIcEntryKeyOffset); 6792 EXPECT_FALSE(key.isValueCell()); 6793} 6794 6795TEST_F(InterpreterTest, 6796 LoadMethodWithModuleAndNonFunctionRewritesToLoadMethodModule) { 6797 EXPECT_FALSE(runFromCStr(runtime_, R"( 6798import sys 6799 6800class C: 6801 def __call__(self): 6802 return 123 6803 6804mymodule = type(sys)("mymodule") 6805mymodule.getdefaultencoding = C() 6806 6807def test(obj): 6808 return obj.getdefaultencoding() 6809)") 6810 .isError()); 6811 HandleScope scope(thread_); 6812 Function test_function(&scope, mainModuleAt(runtime_, "test")); 6813 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 6814 Module mymodule(&scope, mainModuleAt(runtime_, "mymodule")); 6815 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6816 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 2), CALL_METHOD); 6817 6818 // Cache miss. 6819 MutableTuple caches(&scope, test_function.caches()); 6820 word cache_index = 6821 rewrittenBytecodeCacheAt(bytecode, 1) * kIcPointersPerEntry; 6822 Object key(&scope, caches.at(cache_index + kIcEntryKeyOffset)); 6823 EXPECT_EQ(*key, NoneType::object()); 6824 6825 // Call. 6826 EXPECT_TRUE(isIntEqualsWord( 6827 Interpreter::call1(thread_, test_function, mymodule), 123)); 6828 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_MODULE); 6829} 6830 6831TEST_F(InterpreterTest, LoadMethodModuleGetsEvicted) { 6832 EXPECT_FALSE(runFromCStr(runtime_, R"( 6833import sys 6834 6835def test(obj): 6836 return obj.getdefaultencoding() 6837)") 6838 .isError()); 6839 HandleScope scope(thread_); 6840 Function test_function(&scope, mainModuleAt(runtime_, "test")); 6841 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 6842 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6843 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 2), CALL_METHOD); 6844 6845 // Cache miss. 6846 Module sys_module(&scope, runtime_->findModuleById(ID(sys))); 6847 MutableTuple caches(&scope, test_function.caches()); 6848 word cache_index = 6849 rewrittenBytecodeCacheAt(bytecode, 1) * kIcPointersPerEntry; 6850 Object key(&scope, caches.at(cache_index + kIcEntryKeyOffset)); 6851 EXPECT_EQ(*key, NoneType::object()); 6852 6853 // Call. 6854 EXPECT_TRUE(isStrEqualsCStr( 6855 Interpreter::call1(thread_, test_function, sys_module), "utf-8")); 6856 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_MODULE); 6857 6858 // Update module. 6859 Str getdefaultencoding( 6860 &scope, runtime_->internStrFromCStr(thread_, "getdefaultencoding")); 6861 Object result(&scope, 6862 moduleDeleteAttribute(thread_, sys_module, getdefaultencoding)); 6863 ASSERT_TRUE(result.isNoneType()); 6864 6865 // Cache is empty. 6866 key = caches.at(cache_index + kIcEntryKeyOffset); 6867 EXPECT_TRUE(key.isNoneType()); 6868 6869 // Cache miss. 6870 EXPECT_TRUE( 6871 raisedWithStr(Interpreter::call1(thread_, test_function, sys_module), 6872 LayoutId::kAttributeError, 6873 "module 'sys' has no attribute 'getdefaultencoding'")); 6874 6875 // Bytecode gets rewritten after next call. 6876 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6877} 6878 6879TEST_F(InterpreterTest, LoadMethodModuleWithModuleMismatchUpdatesCache) { 6880 EXPECT_FALSE(runFromCStr(runtime_, R"( 6881import sys 6882 6883mymodule = type(sys)("mymodule") 6884mymodule.getdefaultencoding = lambda: "hello" 6885 6886def test(obj): 6887 return obj.getdefaultencoding() 6888)") 6889 .isError()); 6890 HandleScope scope(thread_); 6891 Function test_function(&scope, mainModuleAt(runtime_, "test")); 6892 Module mymodule(&scope, mainModuleAt(runtime_, "mymodule")); 6893 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 6894 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6895 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 2), CALL_METHOD); 6896 6897 // Cache miss. 6898 Module sys_module(&scope, runtime_->findModuleById(ID(sys))); 6899 MutableTuple caches(&scope, test_function.caches()); 6900 word cache_index = 6901 rewrittenBytecodeCacheAt(bytecode, 1) * kIcPointersPerEntry; 6902 Object key(&scope, caches.at(cache_index + kIcEntryKeyOffset)); 6903 EXPECT_EQ(*key, NoneType::object()); 6904 6905 // Call. 6906 EXPECT_TRUE(isStrEqualsCStr( 6907 Interpreter::call1(thread_, test_function, sys_module), "utf-8")); 6908 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_MODULE); 6909 6910 // Cache contains sys. 6911 key = caches.at(cache_index + kIcEntryKeyOffset); 6912 EXPECT_TRUE(isIntEqualsWord(*key, sys_module.id())); 6913 6914 // Call. 6915 EXPECT_TRUE(isStrEqualsCStr( 6916 Interpreter::call1(thread_, test_function, mymodule), "hello")); 6917 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_MODULE); 6918 6919 // Cache contains mymodule. 6920 key = caches.at(cache_index + kIcEntryKeyOffset); 6921 EXPECT_TRUE(isIntEqualsWord(*key, mymodule.id())); 6922} 6923 6924TEST_F(InterpreterTest, LoadMethodModuleGetsScannedInOtherEviction) { 6925 EXPECT_FALSE(runFromCStr(runtime_, R"( 6926import sys 6927 6928class C: 6929 def __init__(self): 6930 self.foo = 123 6931 6932c = C() 6933 6934def test(obj): 6935 c.foo 6936 return obj.getdefaultencoding() 6937 6938def invalidate(): 6939 C.foo = property(lambda self: 456) 6940)") 6941 .isError()); 6942 HandleScope scope(thread_); 6943 Function test_function(&scope, mainModuleAt(runtime_, "test")); 6944 Function invalidate(&scope, mainModuleAt(runtime_, "invalidate")); 6945 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 6946 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 4), LOAD_METHOD_ANAMORPHIC); 6947 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 5), CALL_METHOD); 6948 6949 // Cache miss. 6950 Module sys_module(&scope, runtime_->findModuleById(ID(sys))); 6951 MutableTuple caches(&scope, test_function.caches()); 6952 word cache_index = 6953 rewrittenBytecodeCacheAt(bytecode, 4) * kIcPointersPerEntry; 6954 Object key(&scope, caches.at(cache_index + kIcEntryKeyOffset)); 6955 EXPECT_EQ(*key, NoneType::object()); 6956 6957 // Call. 6958 EXPECT_TRUE(isStrEqualsCStr( 6959 Interpreter::call1(thread_, test_function, sys_module), "utf-8")); 6960 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 4), LOAD_METHOD_MODULE); 6961 6962 // Evict the caches in the `test' function. 6963 ASSERT_TRUE(Interpreter::call0(thread_, invalidate).isNoneType()); 6964 6965 // The LOAD_METHOD_MODULE is not affected. 6966 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 4), LOAD_METHOD_MODULE); 6967 EXPECT_TRUE(isStrEqualsCStr( 6968 Interpreter::call1(thread_, test_function, sys_module), "utf-8")); 6969 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 4), LOAD_METHOD_MODULE); 6970} 6971 6972TEST_F(InterpreterTest, LoadMethodCachedDoesNotCacheProperty) { 6973 HandleScope scope(thread_); 6974 EXPECT_FALSE(runFromCStr(runtime_, R"( 6975class C: 6976 @property 6977 def foo(self): return lambda: 1234 6978 6979def call_foo(c): 6980 return c.foo() 6981 6982c = C() 6983call_foo(c) 6984)") 6985 .isError()); 6986 Function call_foo(&scope, mainModuleAt(runtime_, "call_foo")); 6987 MutableBytes bytecode(&scope, call_foo.rewrittenBytecode()); 6988 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 6989 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 2), CALL_METHOD); 6990 6991 MutableTuple caches(&scope, call_foo.caches()); 6992 EXPECT_TRUE(icIsCacheEmpty(caches, rewrittenBytecodeArgAt(bytecode, 1))); 6993} 6994 6995TEST_F(InterpreterTest, LoadMethodUpdatesOpcodeWithCaching) { 6996 HandleScope scope(thread_); 6997 EXPECT_FALSE(runFromCStr(runtime_, R"( 6998class C: 6999 def foo(self): 7000 return 4 7001 7002class D: 7003 def foo(self): 7004 return -4 7005 7006def test(c): 7007 return c.foo() 7008 7009c = C() 7010d = D() 7011)") 7012 .isError()); 7013 Function test_function(&scope, mainModuleAt(runtime_, "test")); 7014 Object c(&scope, mainModuleAt(runtime_, "c")); 7015 Object d(&scope, mainModuleAt(runtime_, "d")); 7016 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 7017 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_ANAMORPHIC); 7018 ASSERT_TRUE( 7019 isIntEqualsWord(Interpreter::call1(thread_, test_function, c), 4)); 7020 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_INSTANCE_FUNCTION); 7021 7022 ASSERT_TRUE( 7023 isIntEqualsWord(Interpreter::call1(thread_, test_function, d), -4)); 7024 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_METHOD_POLYMORPHIC); 7025} 7026 7027TEST_F(InterpreterTest, DoLoadImmediate) { 7028 HandleScope scope(thread_); 7029 EXPECT_FALSE(runFromCStr(runtime_, R"( 7030def test(): 7031 return None 7032 7033result = test() 7034)") 7035 .isError()); 7036 Function test_function(&scope, mainModuleAt(runtime_, "test")); 7037 MutableBytes bytecode(&scope, test_function.rewrittenBytecode()); 7038 // Verify that rewriting replaces LOAD_CONST for LOAD_IMMEDIATE. 7039 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 0), LOAD_IMMEDIATE); 7040 EXPECT_EQ(rewrittenBytecodeArgAt(bytecode, 0), 7041 static_cast<byte>(NoneType::object().raw())); 7042 EXPECT_TRUE(mainModuleAt(runtime_, "result").isNoneType()); 7043} 7044 7045TEST_F(InterpreterTest, LoadAttrCachedInsertsExecutingFunctionAsDependent) { 7046 EXPECT_FALSE(runFromCStr(runtime_, R"( 7047class C: 7048 def __init__(self): 7049 self.foo = 400 7050 7051def cache_attribute(c): 7052 return c.foo 7053 7054c = C() 7055)") 7056 .isError()); 7057 HandleScope scope(thread_); 7058 Type type_c(&scope, mainModuleAt(runtime_, "C")); 7059 Object c(&scope, mainModuleAt(runtime_, "c")); 7060 Function cache_attribute(&scope, mainModuleAt(runtime_, "cache_attribute")); 7061 MutableTuple caches(&scope, cache_attribute.caches()); 7062 ASSERT_EQ(caches.length(), 2 * kIcPointersPerEntry); 7063 7064 // Load the cache. 7065 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 7066 ASSERT_TRUE( 7067 isIntEqualsWord(Interpreter::call1(thread_, cache_attribute, c), 400)); 7068 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isSmallInt()); 7069 7070 // Verify that cache_attribute function is added as a dependent. 7071 Object foo_name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 7072 ValueCell value_cell(&scope, typeValueCellAt(*type_c, *foo_name)); 7073 ASSERT_TRUE(value_cell.dependencyLink().isWeakLink()); 7074 EXPECT_EQ(WeakLink::cast(value_cell.dependencyLink()).referent(), 7075 *cache_attribute); 7076} 7077 7078TEST_F(InterpreterTest, LoadAttrDunderClassRewritesToLoadType) { 7079 EXPECT_FALSE(runFromCStr(runtime_, R"( 7080class C: 7081 pass 7082 7083class D: 7084 @property 7085 def __class__(self): 7086 return 123 7087 7088def cache_attribute(c): 7089 return c.__class__ 7090 7091c = C() 7092d = D() 7093)") 7094 .isError()); 7095 HandleScope scope(thread_); 7096 Type type_c(&scope, mainModuleAt(runtime_, "C")); 7097 Object c(&scope, mainModuleAt(runtime_, "c")); 7098 Function cache_attribute(&scope, mainModuleAt(runtime_, "cache_attribute")); 7099 MutableBytes bytecode(&scope, cache_attribute.rewrittenBytecode()); 7100 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_ATTR_ANAMORPHIC); 7101 MutableTuple caches(&scope, cache_attribute.caches()); 7102 ASSERT_EQ(caches.length(), 2 * kIcPointersPerEntry); 7103 7104 // Load the cache. 7105 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 7106 ASSERT_EQ(Interpreter::call1(thread_, cache_attribute, c), *type_c); 7107 // It won't be in the cache. 7108 EXPECT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 7109 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_TYPE); 7110 7111 // Verify that cache_attribute function is added as a dependent. 7112 Object attr_name(&scope, Runtime::internStrFromCStr(thread_, "__class__")); 7113 ValueCell value_cell(&scope, typeValueCellAt(*type_c, *attr_name)); 7114 ASSERT_TRUE(value_cell.dependencyLink().isWeakLink()); 7115 EXPECT_EQ(WeakLink::cast(value_cell.dependencyLink()).referent(), 7116 *cache_attribute); 7117 7118 // Invalidate the cache with something that overrides __class__. 7119 Object d(&scope, mainModuleAt(runtime_, "d")); 7120 ASSERT_TRUE( 7121 isIntEqualsWord(Interpreter::call1(thread_, cache_attribute, d), 123)); 7122 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_ATTR_INSTANCE_PROPERTY); 7123} 7124 7125TEST_F(InterpreterTest, LoadAttrDunderClassWithPropertyDoesNotCache) { 7126 EXPECT_FALSE(runFromCStr(runtime_, R"( 7127class C: 7128 @property 7129 def __class__(self): 7130 return 5 7131 7132def cache_attribute(c): 7133 return c.__class__ 7134 7135c = C() 7136)") 7137 .isError()); 7138 HandleScope scope(thread_); 7139 Object c(&scope, mainModuleAt(runtime_, "c")); 7140 Function cache_attribute(&scope, mainModuleAt(runtime_, "cache_attribute")); 7141 MutableBytes bytecode(&scope, cache_attribute.rewrittenBytecode()); 7142 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_ATTR_ANAMORPHIC); 7143 MutableTuple caches(&scope, cache_attribute.caches()); 7144 ASSERT_EQ(caches.length(), 2 * kIcPointersPerEntry); 7145 7146 // Load the cache. 7147 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 7148 ASSERT_TRUE( 7149 isIntEqualsWord(Interpreter::call1(thread_, cache_attribute, c), 5)); 7150 // It is a cached property getter, not LOAD_TYPE. 7151 EXPECT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isFunction()); 7152 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_ATTR_INSTANCE_PROPERTY); 7153} 7154 7155TEST_F(InterpreterTest, 7156 LoadAttrInstanceOnInvalidatedCacheUpdatesCacheCorrectly) { 7157 EXPECT_FALSE(runFromCStr(runtime_, R"( 7158class C: 7159 def __init__(self): 7160 self.foo = "instance attribute" 7161 7162def cache_attribute(c): 7163 return c.foo 7164 7165def invalidate_attribute(c): 7166 C.foo = property(lambda e: "descriptor attribute") 7167 7168c = C() 7169)") 7170 .isError()); 7171 HandleScope scope(thread_); 7172 Object c(&scope, mainModuleAt(runtime_, "c")); 7173 Function cache_attribute(&scope, mainModuleAt(runtime_, "cache_attribute")); 7174 MutableBytes bytecode(&scope, cache_attribute.rewrittenBytecode()); 7175 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_ATTR_ANAMORPHIC); 7176 Tuple caches(&scope, cache_attribute.caches()); 7177 ASSERT_EQ(caches.length(), 2 * kIcPointersPerEntry); 7178 7179 // Load the cache. 7180 ASSERT_EQ(icCurrentState(*caches, 1), ICState::kAnamorphic); 7181 ASSERT_TRUE(isStrEqualsCStr(Interpreter::call1(thread_, cache_attribute, c), 7182 "instance attribute")); 7183 ASSERT_EQ(icCurrentState(*caches, 1), ICState::kMonomorphic); 7184 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_ATTR_INSTANCE); 7185 7186 // Invalidate the cache. 7187 Function invalidate_attribute(&scope, 7188 mainModuleAt(runtime_, "invalidate_attribute")); 7189 ASSERT_TRUE( 7190 Interpreter::call1(thread_, invalidate_attribute, c).isNoneType()); 7191 ASSERT_EQ(icCurrentState(*caches, 1), ICState::kAnamorphic); 7192 ASSERT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_ATTR_INSTANCE); 7193 7194 // Load the cache again. 7195 EXPECT_TRUE(isStrEqualsCStr(Interpreter::call1(thread_, cache_attribute, c), 7196 "descriptor attribute")); 7197 EXPECT_EQ(icCurrentState(*caches, 1), ICState::kMonomorphic); 7198 EXPECT_EQ(rewrittenBytecodeOpAt(bytecode, 1), LOAD_ATTR_INSTANCE_PROPERTY); 7199} 7200 7201TEST_F(InterpreterTest, StoreAttrCachedInsertsExecutingFunctionAsDependent) { 7202 EXPECT_FALSE(runFromCStr(runtime_, R"( 7203class C: 7204 def __init__(self): 7205 self.foo = 400 7206 7207def cache_attribute(c): 7208 c.foo = 500 7209 7210c = C() 7211)") 7212 .isError()); 7213 HandleScope scope(thread_); 7214 Type type_c(&scope, mainModuleAt(runtime_, "C")); 7215 Object c(&scope, mainModuleAt(runtime_, "c")); 7216 Function cache_attribute(&scope, mainModuleAt(runtime_, "cache_attribute")); 7217 MutableTuple caches(&scope, cache_attribute.caches()); 7218 ASSERT_EQ(caches.length(), 2 * kIcPointersPerEntry); 7219 7220 // Load the cache. 7221 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isErrorNotFound()); 7222 ASSERT_TRUE(Interpreter::call1(thread_, cache_attribute, c).isNoneType()); 7223 ASSERT_TRUE(icLookupAttr(*caches, 1, c.layoutId()).isSmallInt()); 7224 7225 // Verify that cache_attribute function is added as a dependent. 7226 Object foo_name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 7227 ValueCell value_cell(&scope, typeValueCellAt(*type_c, *foo_name)); 7228 ASSERT_TRUE(value_cell.dependencyLink().isWeakLink()); 7229 EXPECT_EQ(WeakLink::cast(value_cell.dependencyLink()).referent(), 7230 *cache_attribute); 7231} 7232 7233TEST_F(InterpreterTest, StoreAttrsCausingShadowingInvalidatesCache) { 7234 EXPECT_FALSE(runFromCStr(runtime_, R"( 7235class A: 7236 def foo(self): return 40 7237 7238class B(A): 7239 def foo(self): return 50 7240 7241class C(B): 7242 pass 7243 7244def function_that_caches_attr_lookup(a, b, c): 7245 return a.foo() + b.foo() + c.foo() 7246 7247def func_that_causes_shadowing_of_attr_a(): 7248 A.foo = lambda self: 300 7249 7250def func_that_causes_shadowing_of_attr_b(): 7251 B.foo = lambda self: 200 7252 7253 7254# Caching A.foo and B.foo in cache_attribute. 7255a = A() 7256b = B() 7257c = C() 7258a_foo = A.foo 7259b_foo = B.foo 7260function_that_caches_attr_lookup(a, b, c) 7261)") 7262 .isError()); 7263 HandleScope scope(thread_); 7264 Type type_a(&scope, mainModuleAt(runtime_, "A")); 7265 Type type_b(&scope, mainModuleAt(runtime_, "B")); 7266 Type type_c(&scope, mainModuleAt(runtime_, "C")); 7267 Object a(&scope, mainModuleAt(runtime_, "a")); 7268 Object b(&scope, mainModuleAt(runtime_, "b")); 7269 Object c(&scope, mainModuleAt(runtime_, "c")); 7270 Function function_that_caches_attr_lookup( 7271 &scope, mainModuleAt(runtime_, "function_that_caches_attr_lookup")); 7272 MutableTuple caches(&scope, function_that_caches_attr_lookup.caches()); 7273 // 0: global variable 7274 // 1: a.foo 7275 // 2: b.foo 7276 // 3: binary op cache 7277 // 4: c.foo 7278 // 5, binary op cache 7279 Function a_foo(&scope, mainModuleAt(runtime_, "a_foo")); 7280 Function b_foo(&scope, mainModuleAt(runtime_, "b_foo")); 7281 ASSERT_EQ(caches.length(), 6 * kIcPointersPerEntry); 7282 ASSERT_EQ(icLookupAttr(*caches, 1, a.layoutId()), *a_foo); 7283 ASSERT_EQ(icLookupAttr(*caches, 2, b.layoutId()), *b_foo); 7284 ASSERT_EQ(icLookupAttr(*caches, 4, c.layoutId()), *b_foo); 7285 7286 // Verify that function_that_caches_attr_lookup cached the attribute lookup 7287 // and appears on the dependency list of A.foo. 7288 Object foo_name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 7289 ValueCell foo_in_a(&scope, typeValueCellAt(*type_a, *foo_name)); 7290 ASSERT_TRUE(foo_in_a.dependencyLink().isWeakLink()); 7291 ASSERT_EQ(WeakLink::cast(foo_in_a.dependencyLink()).referent(), 7292 *function_that_caches_attr_lookup); 7293 7294 // Verify that function_that_caches_attr_lookup cached the attribute lookup 7295 // and appears on the dependency list of B.foo. 7296 ValueCell foo_in_b(&scope, typeValueCellAt(*type_b, *foo_name)); 7297 ASSERT_TRUE(foo_in_b.dependencyLink().isWeakLink()); 7298 ASSERT_EQ(WeakLink::cast(foo_in_b.dependencyLink()).referent(), 7299 *function_that_caches_attr_lookup); 7300 7301 // Verify that function_that_caches_attr_lookup cached the attribute lookup 7302 // and appears on the dependency list of C.foo. 7303 ValueCell foo_in_c(&scope, typeValueCellAt(*type_c, *foo_name)); 7304 ASSERT_TRUE(foo_in_c.dependencyLink().isWeakLink()); 7305 ASSERT_EQ(WeakLink::cast(foo_in_c.dependencyLink()).referent(), 7306 *function_that_caches_attr_lookup); 7307 7308 // Change the class A so that any caches that reference A.foo are invalidated. 7309 Function func_that_causes_shadowing_of_attr_a( 7310 &scope, mainModuleAt(runtime_, "func_that_causes_shadowing_of_attr_a")); 7311 ASSERT_TRUE(Interpreter::call0(thread_, func_that_causes_shadowing_of_attr_a) 7312 .isNoneType()); 7313 // Verify that the cache for A.foo is cleared out, and dependent does not 7314 // depend on A.foo anymore. 7315 EXPECT_TRUE(icLookupAttr(*caches, 1, a.layoutId()).isErrorNotFound()); 7316 EXPECT_TRUE(foo_in_a.dependencyLink().isNoneType()); 7317 // Check that any lookups of B have not been invalidated. 7318 EXPECT_EQ(icLookupAttr(*caches, 2, b.layoutId()), *b_foo); 7319 EXPECT_EQ(WeakLink::cast(foo_in_b.dependencyLink()).referent(), 7320 *function_that_caches_attr_lookup); 7321 // Check that any lookups of C have not been invalidated. 7322 EXPECT_EQ(icLookupAttr(*caches, 4, c.layoutId()), *b_foo); 7323 EXPECT_EQ(WeakLink::cast(foo_in_c.dependencyLink()).referent(), 7324 *function_that_caches_attr_lookup); 7325 7326 // Invalidate the cache for B.foo. 7327 Function func_that_causes_shadowing_of_attr_b( 7328 &scope, mainModuleAt(runtime_, "func_that_causes_shadowing_of_attr_b")); 7329 ASSERT_TRUE(Interpreter::call0(thread_, func_that_causes_shadowing_of_attr_b) 7330 .isNoneType()); 7331 // Check that caches for A are still invalidated. 7332 EXPECT_TRUE(icLookupAttr(*caches, 1, a.layoutId()).isErrorNotFound()); 7333 EXPECT_TRUE(foo_in_a.dependencyLink().isNoneType()); 7334 // Check that caches for B and C got just invalidated since they refer to 7335 // B.foo. 7336 EXPECT_TRUE(icLookupAttr(*caches, 2, b.layoutId()).isErrorNotFound()); 7337 EXPECT_TRUE(foo_in_b.dependencyLink().isNoneType()); 7338 EXPECT_TRUE(icLookupAttr(*caches, 4, c.layoutId()).isErrorNotFound()); 7339 EXPECT_TRUE(foo_in_c.dependencyLink().isNoneType()); 7340} 7341 7342TEST_F(InterpreterTest, IntrinsicWithSlowPathDoesNotAlterStack) { 7343 HandleScope scope(thread_); 7344 Object obj(&scope, runtime_->newList()); 7345 thread_->stackPush(*obj); 7346 Module module(&scope, runtime_->findModuleById(ID(_builtins))); 7347 Function tuple_len_func(&scope, 7348 moduleAtById(thread_, module, ID(_tuple_len))); 7349 IntrinsicFunction function = 7350 reinterpret_cast<IntrinsicFunction>(tuple_len_func.intrinsic()); 7351 ASSERT_NE(function, nullptr); 7352 ASSERT_FALSE(function(thread_)); 7353 EXPECT_EQ(thread_->stackPeek(0), *obj); 7354} 7355 7356TEST_F(JitTest, CompileFunctionSetsEntryAsm) { 7357 if (useCppInterpreter()) { 7358 GTEST_SKIP(); 7359 } 7360 HandleScope scope(thread_); 7361 Object obj1(&scope, NoneType::object()); 7362 Tuple consts(&scope, runtime_->newTupleWith1(obj1)); 7363 const byte bytecode[] = { 7364 LOAD_CONST, 7365 0, 7366 RETURN_VALUE, 7367 0, 7368 }; 7369 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 7370 Object qualname(&scope, Str::empty()); 7371 Module module(&scope, findMainModule(runtime_)); 7372 Function function( 7373 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 7374 void* entry_before = function.entryAsm(); 7375 compileFunction(thread_, function); 7376 EXPECT_NE(function.entryAsm(), entry_before); 7377} 7378 7379// Create the function: 7380// def caller(): 7381// return foo() 7382// without rewriting the bytecode. 7383static RawObject createTrampolineFunction(Thread* thread) { 7384 HandleScope scope(thread); 7385 Str foo(&scope, Runtime::internStrFromCStr(thread, "foo")); 7386 Runtime* runtime = thread->runtime(); 7387 Tuple names(&scope, runtime->newTupleWith1(foo)); 7388 Tuple consts(&scope, runtime->emptyTuple()); 7389 const byte bytecode[] = { 7390 LOAD_GLOBAL, 0, CALL_FUNCTION, 0, RETURN_VALUE, 0, 7391 }; 7392 Code code(&scope, newCodeWithBytesConstsNames(bytecode, consts, names)); 7393 Str qualname(&scope, runtime->newStrFromCStr("qualname")); 7394 Module module(&scope, findMainModule(runtime)); 7395 Function function( 7396 &scope, runtime->newFunctionWithCode(thread, qualname, code, module)); 7397 Bytes bytecode_bytes(&scope, runtime->newBytesWithAll(bytecode)); 7398 MutableBytes rewritten(&scope, expandBytecode(thread, bytecode_bytes)); 7399 function.setRewrittenBytecode(*rewritten); 7400 return *function; 7401} 7402 7403// Create the function: 7404// def caller(): 7405// return foo(obj) 7406// where obj is the parameter to createTrampolineFunction1, without rewriting 7407// the bytecode. 7408static RawObject createTrampolineFunction1(Thread* thread, const Object& obj) { 7409 HandleScope scope(thread); 7410 Str foo(&scope, Runtime::internStrFromCStr(thread, "foo")); 7411 Runtime* runtime = thread->runtime(); 7412 Tuple names(&scope, runtime->newTupleWith1(foo)); 7413 Tuple consts(&scope, runtime->newTupleWith1(obj)); 7414 const byte bytecode[] = { 7415 LOAD_GLOBAL, 0, LOAD_CONST, 0, CALL_FUNCTION, 1, RETURN_VALUE, 0, 7416 }; 7417 Code code(&scope, newCodeWithBytesConstsNames(bytecode, consts, names)); 7418 Str qualname(&scope, runtime->newStrFromCStr("qualname")); 7419 Module module(&scope, findMainModule(runtime)); 7420 Function function( 7421 &scope, runtime->newFunctionWithCode(thread, qualname, code, module)); 7422 Bytes bytecode_bytes(&scope, runtime->newBytesWithAll(bytecode)); 7423 MutableBytes rewritten(&scope, expandBytecode(thread, bytecode_bytes)); 7424 function.setRewrittenBytecode(*rewritten); 7425 return *function; 7426} 7427 7428// Create the function: 7429// def caller(): 7430// return foo(left, right) 7431// where obj is the parameter to createTrampolineFunction2, without rewriting 7432// the bytecode. 7433static RawObject createTrampolineFunction2(Thread* thread, const Object& left, 7434 const Object& right) { 7435 HandleScope scope(thread); 7436 Str foo(&scope, Runtime::internStrFromCStr(thread, "foo")); 7437 Runtime* runtime = thread->runtime(); 7438 Tuple names(&scope, runtime->newTupleWith1(foo)); 7439 Tuple consts(&scope, runtime->newTupleWith2(left, right)); 7440 const byte bytecode[] = { 7441 LOAD_GLOBAL, 0, LOAD_CONST, 0, LOAD_CONST, 1, 7442 CALL_FUNCTION, 2, RETURN_VALUE, 0, 7443 }; 7444 Code code(&scope, newCodeWithBytesConstsNames(bytecode, consts, names)); 7445 Str qualname(&scope, runtime->newStrFromCStr("qualname")); 7446 Module module(&scope, findMainModule(runtime)); 7447 Function function( 7448 &scope, runtime->newFunctionWithCode(thread, qualname, code, module)); 7449 Bytes bytecode_bytes(&scope, runtime->newBytesWithAll(bytecode)); 7450 MutableBytes rewritten(&scope, expandBytecode(thread, bytecode_bytes)); 7451 function.setRewrittenBytecode(*rewritten); 7452 return *function; 7453} 7454 7455// Replace the bytecode with an empty bytes object after a function has been 7456// compiled so that the function cannot be interpreted normally. This is useful 7457// for ensuring that we are running the JITed function. 7458static void setEmptyBytecode(const Function& function) { 7459 function.setRewrittenBytecode(SmallBytes::empty()); 7460} 7461 7462static RawObject compileAndCallJITFunction(Thread* thread, 7463 const Function& function) { 7464 HandleScope scope(thread); 7465 Function caller(&scope, createTrampolineFunction(thread)); 7466 compileFunction(thread, function); 7467 setEmptyBytecode(function); 7468 return Interpreter::call0(thread, caller); 7469} 7470 7471static RawObject compileAndCallJITFunction1(Thread* thread, 7472 const Function& function, 7473 const Object& param) { 7474 HandleScope scope(thread); 7475 Function caller(&scope, createTrampolineFunction1(thread, param)); 7476 compileFunction(thread, function); 7477 setEmptyBytecode(function); 7478 return Interpreter::call0(thread, caller); 7479} 7480 7481static RawObject compileAndCallJITFunction2(Thread* thread, 7482 const Function& function, 7483 const Object& param1, 7484 const Object& param2) { 7485 HandleScope scope(thread); 7486 Function caller(&scope, createTrampolineFunction2(thread, param1, param2)); 7487 compileFunction(thread, function); 7488 setEmptyBytecode(function); 7489 return Interpreter::call0(thread, caller); 7490} 7491 7492TEST_F(JitTest, CallFunctionWithTooFewArgsRaisesTypeError) { 7493 if (useCppInterpreter()) { 7494 GTEST_SKIP(); 7495 } 7496 EXPECT_FALSE(runFromCStr(runtime_, R"( 7497def foo(obj): 7498 return (1, 2, 3) 7499)") 7500 .isError()); 7501 7502 HandleScope scope(thread_); 7503 Function function(&scope, mainModuleAt(runtime_, "foo")); 7504 EXPECT_TRUE(containsBytecode(function, LOAD_CONST)); 7505 Object result(&scope, compileAndCallJITFunction(thread_, function)); 7506 EXPECT_TRUE( 7507 raisedWithStr(*result, LayoutId::kTypeError, 7508 "'foo' takes min 1 positional arguments but 0 given")); 7509} 7510 7511// TODO(T89353729): Add test for calling a JIT function with a signal set. 7512 7513TEST_F(JitTest, LoadConstLoadsConstant) { 7514 if (useCppInterpreter()) { 7515 GTEST_SKIP(); 7516 } 7517 EXPECT_FALSE(runFromCStr(runtime_, R"( 7518def foo(): 7519 return (1, 2, 3) 7520)") 7521 .isError()); 7522 7523 HandleScope scope(thread_); 7524 Function function(&scope, mainModuleAt(runtime_, "foo")); 7525 EXPECT_TRUE(containsBytecode(function, LOAD_CONST)); 7526 Object result_obj(&scope, compileAndCallJITFunction(thread_, function)); 7527 ASSERT_TRUE(result_obj.isTuple()); 7528 Tuple result(&scope, *result_obj); 7529 ASSERT_EQ(result.length(), 3); 7530 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1)); 7531 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2)); 7532 EXPECT_TRUE(isIntEqualsWord(result.at(2), 3)); 7533} 7534 7535TEST_F(JitTest, LoadBoolLoadsBool) { 7536 if (useCppInterpreter()) { 7537 GTEST_SKIP(); 7538 } 7539 EXPECT_FALSE(runFromCStr(runtime_, R"( 7540def foo(): 7541 return True 7542)") 7543 .isError()); 7544 7545 HandleScope scope(thread_); 7546 Function function(&scope, mainModuleAt(runtime_, "foo")); 7547 EXPECT_TRUE(containsBytecode(function, LOAD_BOOL)); 7548 Object result(&scope, compileAndCallJITFunction(thread_, function)); 7549 EXPECT_EQ(*result, Bool::trueObj()); 7550} 7551 7552TEST_F(JitTest, LoadImmediateLoadsImmediate) { 7553 if (useCppInterpreter()) { 7554 GTEST_SKIP(); 7555 } 7556 EXPECT_FALSE(runFromCStr(runtime_, R"( 7557def foo(): 7558 return None 7559)") 7560 .isError()); 7561 7562 HandleScope scope(thread_); 7563 Function function(&scope, mainModuleAt(runtime_, "foo")); 7564 EXPECT_TRUE(containsBytecode(function, LOAD_IMMEDIATE)); 7565 Object result(&scope, compileAndCallJITFunction(thread_, function)); 7566 EXPECT_EQ(*result, NoneType::object()); 7567} 7568 7569TEST_F(JitTest, LoadFastReverseLoadsLocal) { 7570 if (useCppInterpreter()) { 7571 GTEST_SKIP(); 7572 } 7573 EXPECT_FALSE(runFromCStr(runtime_, R"( 7574def foo(): 7575 var = 5 7576 return var 7577)") 7578 .isError()); 7579 7580 HandleScope scope(thread_); 7581 Function function(&scope, mainModuleAt(runtime_, "foo")); 7582 EXPECT_TRUE(containsBytecode(function, LOAD_FAST_REVERSE_UNCHECKED)); 7583 Object result(&scope, compileAndCallJITFunction(thread_, function)); 7584 EXPECT_TRUE(isIntEqualsWord(*result, 5)); 7585} 7586 7587TEST_F(JitTest, LoadFastReverseWithUnboundNameRaisesUnboundLocalError) { 7588 if (useCppInterpreter()) { 7589 GTEST_SKIP(); 7590 } 7591 EXPECT_FALSE(runFromCStr(runtime_, R"( 7592def foo(): 7593 var = 5 7594 del var 7595 return var 7596)") 7597 .isError()); 7598 7599 HandleScope scope(thread_); 7600 Function function(&scope, mainModuleAt(runtime_, "foo")); 7601 EXPECT_TRUE(containsBytecode(function, LOAD_FAST_REVERSE)); 7602 void* entry_before = function.entryAsm(); 7603 compileFunction(thread_, function); 7604 EXPECT_NE(function.entryAsm(), entry_before); 7605 Function deopt_caller(&scope, createTrampolineFunction(thread_)); 7606 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 7607 EXPECT_TRUE(raised(*result, LayoutId::kUnboundLocalError)); 7608 EXPECT_EQ(function.entryAsm(), entry_before); 7609} 7610 7611TEST_F(JitTest, LoadFastReverseUncheckedLoadsParameter) { 7612 if (useCppInterpreter()) { 7613 GTEST_SKIP(); 7614 } 7615 EXPECT_FALSE(runFromCStr(runtime_, R"( 7616def foo(param): 7617 return param 7618)") 7619 .isError()); 7620 7621 HandleScope scope(thread_); 7622 Function function(&scope, mainModuleAt(runtime_, "foo")); 7623 EXPECT_TRUE(containsBytecode(function, LOAD_FAST_REVERSE_UNCHECKED)); 7624 Object param(&scope, SmallInt::fromWord(123)); 7625 Object result(&scope, compileAndCallJITFunction1(thread_, function, param)); 7626 EXPECT_TRUE(isIntEqualsWord(*result, 123)); 7627} 7628 7629TEST_F(JitTest, StoreFastReverseWritesToParameter) { 7630 if (useCppInterpreter()) { 7631 GTEST_SKIP(); 7632 } 7633 EXPECT_FALSE(runFromCStr(runtime_, R"( 7634def foo(param): 7635 param = 3 7636 return param 7637)") 7638 .isError()); 7639 7640 HandleScope scope(thread_); 7641 Function function(&scope, mainModuleAt(runtime_, "foo")); 7642 EXPECT_TRUE(containsBytecode(function, LOAD_FAST_REVERSE_UNCHECKED)); 7643 Object param(&scope, SmallInt::fromWord(123)); 7644 Object result(&scope, compileAndCallJITFunction1(thread_, function, param)); 7645 EXPECT_TRUE(isIntEqualsWord(*result, 3)); 7646} 7647 7648TEST_F(JitTest, CompareIsWithSameObjectsReturnsTrue) { 7649 if (useCppInterpreter()) { 7650 GTEST_SKIP(); 7651 } 7652 EXPECT_FALSE(runFromCStr(runtime_, R"( 7653def foo(): 7654 return 123 is 123 7655)") 7656 .isError()); 7657 7658 HandleScope scope(thread_); 7659 Function function(&scope, mainModuleAt(runtime_, "foo")); 7660 EXPECT_TRUE(containsBytecode(function, COMPARE_IS)); 7661 Object result(&scope, compileAndCallJITFunction(thread_, function)); 7662 EXPECT_EQ(*result, Bool::trueObj()); 7663} 7664 7665TEST_F(JitTest, CompareIsWithDifferentObjectsReturnsFalse) { 7666 if (useCppInterpreter()) { 7667 GTEST_SKIP(); 7668 } 7669 EXPECT_FALSE(runFromCStr(runtime_, R"( 7670def foo(): 7671 return 123 is 124 7672)") 7673 .isError()); 7674 7675 HandleScope scope(thread_); 7676 Function function(&scope, mainModuleAt(runtime_, "foo")); 7677 EXPECT_TRUE(containsBytecode(function, COMPARE_IS)); 7678 Object result(&scope, compileAndCallJITFunction(thread_, function)); 7679 EXPECT_EQ(*result, Bool::falseObj()); 7680} 7681 7682TEST_F(JitTest, CompareIsNotWithSameObjectsReturnsFalse) { 7683 if (useCppInterpreter()) { 7684 GTEST_SKIP(); 7685 } 7686 EXPECT_FALSE(runFromCStr(runtime_, R"( 7687def foo(): 7688 return 123 is not 123 7689)") 7690 .isError()); 7691 7692 HandleScope scope(thread_); 7693 Function function(&scope, mainModuleAt(runtime_, "foo")); 7694 EXPECT_TRUE(containsBytecode(function, COMPARE_IS_NOT)); 7695 Object result(&scope, compileAndCallJITFunction(thread_, function)); 7696 EXPECT_EQ(*result, Bool::falseObj()); 7697} 7698 7699TEST_F(JitTest, CompareIsNotWithDifferentObjectsReturnsTrue) { 7700 if (useCppInterpreter()) { 7701 GTEST_SKIP(); 7702 } 7703 EXPECT_FALSE(runFromCStr(runtime_, R"( 7704def foo(): 7705 return 123 is not 124 7706)") 7707 .isError()); 7708 7709 HandleScope scope(thread_); 7710 Function function(&scope, mainModuleAt(runtime_, "foo")); 7711 EXPECT_TRUE(containsBytecode(function, COMPARE_IS_NOT)); 7712 Object result(&scope, compileAndCallJITFunction(thread_, function)); 7713 EXPECT_EQ(*result, Bool::trueObj()); 7714} 7715 7716TEST_F(JitTest, BinaryAddSmallintWithSmallIntsReturnsInt) { 7717 if (useCppInterpreter()) { 7718 GTEST_SKIP(); 7719 } 7720 EXPECT_FALSE(runFromCStr(runtime_, R"( 7721def foo(left, right): 7722 return left + right 7723 7724# Rewrite BINARY_OP_ANAMORPHIC to BINARY_ADD_SMALLINT 7725foo(1, 1) 7726)") 7727 .isError()); 7728 7729 HandleScope scope(thread_); 7730 Function function(&scope, mainModuleAt(runtime_, "foo")); 7731 EXPECT_TRUE(containsBytecode(function, BINARY_ADD_SMALLINT)); 7732 Object left(&scope, SmallInt::fromWord(5)); 7733 Object right(&scope, SmallInt::fromWord(10)); 7734 Object result(&scope, 7735 compileAndCallJITFunction2(thread_, function, left, right)); 7736 EXPECT_TRUE(isIntEqualsWord(*result, 15)); 7737} 7738 7739TEST_F(JitTest, BinaryAndSmallintWithSmallIntsReturnsInt) { 7740 if (useCppInterpreter()) { 7741 GTEST_SKIP(); 7742 } 7743 EXPECT_FALSE(runFromCStr(runtime_, R"( 7744def foo(left, right): 7745 return left & right 7746 7747# Rewrite BINARY_OP_ANAMORPHIC to BINARY_AND_SMALLINT 7748foo(1, 1) 7749)") 7750 .isError()); 7751 7752 HandleScope scope(thread_); 7753 Function function(&scope, mainModuleAt(runtime_, "foo")); 7754 EXPECT_TRUE(containsBytecode(function, BINARY_AND_SMALLINT)); 7755 Object left(&scope, SmallInt::fromWord(0xff)); 7756 Object right(&scope, SmallInt::fromWord(0x0f)); 7757 Object result(&scope, 7758 compileAndCallJITFunction2(thread_, function, left, right)); 7759 EXPECT_TRUE(isIntEqualsWord(*result, 0x0f)); 7760} 7761 7762TEST_F(JitTest, BinaryOrSmallintWithSmallIntsReturnsInt) { 7763 if (useCppInterpreter()) { 7764 GTEST_SKIP(); 7765 } 7766 EXPECT_FALSE(runFromCStr(runtime_, R"( 7767def foo(left, right): 7768 return left | right 7769 7770# Rewrite BINARY_OP_ANAMORPHIC to BINARY_OR_SMALLINT 7771foo(1, 1) 7772)") 7773 .isError()); 7774 7775 HandleScope scope(thread_); 7776 Function function(&scope, mainModuleAt(runtime_, "foo")); 7777 EXPECT_TRUE(containsBytecode(function, BINARY_OR_SMALLINT)); 7778 Object left(&scope, SmallInt::fromWord(0xf0)); 7779 Object right(&scope, SmallInt::fromWord(0x0f)); 7780 Object result(&scope, 7781 compileAndCallJITFunction2(thread_, function, left, right)); 7782 EXPECT_TRUE(isIntEqualsWord(*result, 0xff)); 7783} 7784 7785TEST_F(JitTest, BinarySubSmallintWithSmallIntsReturnsInt) { 7786 if (useCppInterpreter()) { 7787 GTEST_SKIP(); 7788 } 7789 EXPECT_FALSE(runFromCStr(runtime_, R"( 7790def foo(left, right): 7791 return left - right 7792 7793# Rewrite BINARY_OP_ANAMORPHIC to BINARY_SUB_SMALLINT 7794foo(1, 1) 7795)") 7796 .isError()); 7797 7798 HandleScope scope(thread_); 7799 Function function(&scope, mainModuleAt(runtime_, "foo")); 7800 EXPECT_TRUE(containsBytecode(function, BINARY_SUB_SMALLINT)); 7801 Object left(&scope, SmallInt::fromWord(7)); 7802 Object right(&scope, SmallInt::fromWord(4)); 7803 Object result(&scope, 7804 compileAndCallJITFunction2(thread_, function, left, right)); 7805 EXPECT_TRUE(isIntEqualsWord(*result, 3)); 7806} 7807 7808TEST_F(JitTest, CompareEqSmallintWithSmallIntsReturnsBool) { 7809 if (useCppInterpreter()) { 7810 GTEST_SKIP(); 7811 } 7812 EXPECT_FALSE(runFromCStr(runtime_, R"( 7813def foo(left, right): 7814 return left == right 7815 7816# Rewrite BINARY_OP_ANAMORPHIC to COMPARE_EQ_SMALLINT 7817foo(1, 1) 7818)") 7819 .isError()); 7820 7821 HandleScope scope(thread_); 7822 Function function(&scope, mainModuleAt(runtime_, "foo")); 7823 EXPECT_TRUE(containsBytecode(function, COMPARE_EQ_SMALLINT)); 7824 Object left(&scope, SmallInt::fromWord(7)); 7825 Object right(&scope, SmallInt::fromWord(4)); 7826 Object result(&scope, 7827 compileAndCallJITFunction2(thread_, function, left, right)); 7828 EXPECT_EQ(*result, Bool::falseObj()); 7829} 7830 7831TEST_F(JitTest, CompareNeSmallintWithSmallIntsReturnsBool) { 7832 if (useCppInterpreter()) { 7833 GTEST_SKIP(); 7834 } 7835 EXPECT_FALSE(runFromCStr(runtime_, R"( 7836def foo(left, right): 7837 return left != right 7838 7839# Rewrite BINARY_OP_ANAMORPHIC to COMPARE_NE_SMALLINT 7840foo(1, 1) 7841)") 7842 .isError()); 7843 7844 HandleScope scope(thread_); 7845 Function function(&scope, mainModuleAt(runtime_, "foo")); 7846 EXPECT_TRUE(containsBytecode(function, COMPARE_NE_SMALLINT)); 7847 Object left(&scope, SmallInt::fromWord(7)); 7848 Object right(&scope, SmallInt::fromWord(4)); 7849 Object result(&scope, 7850 compileAndCallJITFunction2(thread_, function, left, right)); 7851 EXPECT_EQ(*result, Bool::trueObj()); 7852} 7853 7854TEST_F(JitTest, CompareGtSmallintWithSmallIntsReturnsBool) { 7855 if (useCppInterpreter()) { 7856 GTEST_SKIP(); 7857 } 7858 EXPECT_FALSE(runFromCStr(runtime_, R"( 7859def foo(left, right): 7860 return left > right 7861 7862# Rewrite BINARY_OP_ANAMORPHIC to COMPARE_GT_SMALLINT 7863foo(1, 1) 7864)") 7865 .isError()); 7866 7867 HandleScope scope(thread_); 7868 Function function(&scope, mainModuleAt(runtime_, "foo")); 7869 EXPECT_TRUE(containsBytecode(function, COMPARE_GT_SMALLINT)); 7870 Object left(&scope, SmallInt::fromWord(7)); 7871 Object right(&scope, SmallInt::fromWord(4)); 7872 Object result(&scope, 7873 compileAndCallJITFunction2(thread_, function, left, right)); 7874 EXPECT_EQ(*result, Bool::trueObj()); 7875} 7876 7877TEST_F(JitTest, CompareGeSmallintWithSmallIntsReturnsBool) { 7878 if (useCppInterpreter()) { 7879 GTEST_SKIP(); 7880 } 7881 EXPECT_FALSE(runFromCStr(runtime_, R"( 7882def foo(left, right): 7883 return left >= right 7884 7885# Rewrite BINARY_OP_ANAMORPHIC to COMPARE_GE_SMALLINT 7886foo(1, 1) 7887)") 7888 .isError()); 7889 7890 HandleScope scope(thread_); 7891 Function function(&scope, mainModuleAt(runtime_, "foo")); 7892 EXPECT_TRUE(containsBytecode(function, COMPARE_GE_SMALLINT)); 7893 Object left(&scope, SmallInt::fromWord(7)); 7894 Object right(&scope, SmallInt::fromWord(4)); 7895 Object result(&scope, 7896 compileAndCallJITFunction2(thread_, function, left, right)); 7897 EXPECT_EQ(*result, Bool::trueObj()); 7898} 7899 7900TEST_F(JitTest, CompareLtSmallintWithSmallIntsReturnsBool) { 7901 if (useCppInterpreter()) { 7902 GTEST_SKIP(); 7903 } 7904 EXPECT_FALSE(runFromCStr(runtime_, R"( 7905def foo(left, right): 7906 return left < right 7907 7908# Rewrite BINARY_OP_ANAMORPHIC to COMPARE_LT_SMALLINT 7909foo(1, 1) 7910)") 7911 .isError()); 7912 7913 HandleScope scope(thread_); 7914 Function function(&scope, mainModuleAt(runtime_, "foo")); 7915 EXPECT_TRUE(containsBytecode(function, COMPARE_LT_SMALLINT)); 7916 Object left(&scope, SmallInt::fromWord(7)); 7917 Object right(&scope, SmallInt::fromWord(4)); 7918 Object result(&scope, 7919 compileAndCallJITFunction2(thread_, function, left, right)); 7920 EXPECT_EQ(*result, Bool::falseObj()); 7921} 7922 7923TEST_F(JitTest, CompareLeSmallintWithSmallIntsReturnsBool) { 7924 if (useCppInterpreter()) { 7925 GTEST_SKIP(); 7926 } 7927 EXPECT_FALSE(runFromCStr(runtime_, R"( 7928def foo(left, right): 7929 return left <= right 7930 7931# Rewrite BINARY_OP_ANAMORPHIC to COMPARE_LE_SMALLINT 7932foo(1, 1) 7933)") 7934 .isError()); 7935 7936 HandleScope scope(thread_); 7937 Function function(&scope, mainModuleAt(runtime_, "foo")); 7938 EXPECT_TRUE(containsBytecode(function, COMPARE_LE_SMALLINT)); 7939 Object left(&scope, SmallInt::fromWord(7)); 7940 Object right(&scope, SmallInt::fromWord(4)); 7941 Object result(&scope, 7942 compileAndCallJITFunction2(thread_, function, left, right)); 7943 EXPECT_EQ(*result, Bool::falseObj()); 7944} 7945 7946TEST_F(JitTest, UnaryNotWithBoolReturnsBool) { 7947 if (useCppInterpreter()) { 7948 GTEST_SKIP(); 7949 } 7950 EXPECT_FALSE(runFromCStr(runtime_, R"( 7951def foo(obj): 7952 return not obj 7953)") 7954 .isError()); 7955 7956 HandleScope scope(thread_); 7957 Function function(&scope, mainModuleAt(runtime_, "foo")); 7958 EXPECT_TRUE(containsBytecode(function, UNARY_NOT)); 7959 Object param(&scope, Bool::trueObj()); 7960 Object result(&scope, compileAndCallJITFunction1(thread_, function, param)); 7961 EXPECT_EQ(*result, Bool::falseObj()); 7962} 7963 7964TEST_F(JitTest, BinaryAddSmallintWithNonSmallintDeoptimizes) { 7965 if (useCppInterpreter()) { 7966 GTEST_SKIP(); 7967 } 7968 // Don't use compileAndCallJITFunction2 in this function because we want to 7969 // test deoptimizing back into the interpreter. This requires valid bytecode. 7970 EXPECT_FALSE(runFromCStr(runtime_, R"( 7971def foo(left, right): 7972 return left + right 7973 7974# Rewrite BINARY_OP_ANAMORPHIC to BINARY_ADD_SMALLINT 7975foo(1, 1) 7976)") 7977 .isError()); 7978 7979 HandleScope scope(thread_); 7980 Function function(&scope, mainModuleAt(runtime_, "foo")); 7981 EXPECT_TRUE(containsBytecode(function, BINARY_ADD_SMALLINT)); 7982 Object left_int(&scope, SmallInt::fromWord(5)); 7983 Object right_int(&scope, SmallInt::fromWord(10)); 7984 void* entry_before = function.entryAsm(); 7985 Function caller(&scope, 7986 createTrampolineFunction2(thread_, left_int, right_int)); 7987 compileFunction(thread_, function); 7988 Object result(&scope, Interpreter::call0(thread_, caller)); 7989 EXPECT_NE(function.entryAsm(), entry_before); 7990 Object left_str(&scope, SmallStr::fromCStr("hello")); 7991 Object right_str(&scope, SmallStr::fromCStr(" world")); 7992 Function deopt_caller( 7993 &scope, createTrampolineFunction2(thread_, left_str, right_str)); 7994 result = Interpreter::call0(thread_, deopt_caller); 7995 EXPECT_TRUE(containsBytecode(function, BINARY_OP_MONOMORPHIC)); 7996 EXPECT_TRUE(isStrEqualsCStr(*result, "hello world")); 7997 EXPECT_EQ(function.entryAsm(), entry_before); 7998} 7999 8000TEST_F(JitTest, BinarySubscrListReturnsItem) { 8001 if (useCppInterpreter()) { 8002 GTEST_SKIP(); 8003 } 8004 EXPECT_FALSE(runFromCStr(runtime_, R"( 8005def foo(obj): 8006 return obj[0] 8007 8008# Rewrite BINARY_SUBSCR_ANAMORPHIC to BINARY_SUBSCR_LIST 8009foo([3, 2, 1]) 8010)") 8011 .isError()); 8012 8013 HandleScope scope(thread_); 8014 Function function(&scope, mainModuleAt(runtime_, "foo")); 8015 EXPECT_TRUE(containsBytecode(function, BINARY_SUBSCR_LIST)); 8016 List list(&scope, runtime_->newList()); 8017 Object obj(&scope, SmallStr::fromCStr("bar")); 8018 runtime_->listAdd(thread_, list, obj); 8019 Object result(&scope, compileAndCallJITFunction1(thread_, function, list)); 8020 EXPECT_TRUE(isStrEqualsCStr(*result, "bar")); 8021} 8022 8023TEST_F(JitTest, BinarySubscrListWithNonListDeoptimizes) { 8024 if (useCppInterpreter()) { 8025 GTEST_SKIP(); 8026 } 8027 EXPECT_FALSE(runFromCStr(runtime_, R"( 8028def foo(obj): 8029 return obj[0] 8030 8031# Rewrite BINARY_SUBSCR_ANAMORPHIC to BINARY_SUBSCR_LIST 8032foo([3, 2, 1]) 8033)") 8034 .isError()); 8035 8036 HandleScope scope(thread_); 8037 Function function(&scope, mainModuleAt(runtime_, "foo")); 8038 EXPECT_TRUE(containsBytecode(function, BINARY_SUBSCR_LIST)); 8039 void* entry_before = function.entryAsm(); 8040 compileFunction(thread_, function); 8041 EXPECT_NE(function.entryAsm(), entry_before); 8042 Object obj(&scope, SmallInt::fromWord(7)); 8043 Object non_list(&scope, runtime_->newTupleWith1(obj)); 8044 Function deopt_caller(&scope, createTrampolineFunction1(thread_, non_list)); 8045 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8046 EXPECT_TRUE(containsBytecode(function, BINARY_SUBSCR_MONOMORPHIC)); 8047 EXPECT_TRUE(isIntEqualsWord(*result, 7)); 8048 EXPECT_EQ(function.entryAsm(), entry_before); 8049} 8050 8051TEST_F(JitTest, StoreSubscrListStoresItem) { 8052 if (useCppInterpreter()) { 8053 GTEST_SKIP(); 8054 } 8055 EXPECT_FALSE(runFromCStr(runtime_, R"( 8056def foo(obj): 8057 obj[0] = 123 8058 8059# Rewrite STORE_SUBSCR_ANAMORPHIC to STORE_SUBSCR_LIST 8060foo([3, 2, 1]) 8061)") 8062 .isError()); 8063 8064 HandleScope scope(thread_); 8065 Function function(&scope, mainModuleAt(runtime_, "foo")); 8066 EXPECT_TRUE(containsBytecode(function, STORE_SUBSCR_LIST)); 8067 List list(&scope, runtime_->newList()); 8068 Object obj(&scope, SmallStr::fromCStr("bar")); 8069 runtime_->listAdd(thread_, list, obj); 8070 Object result(&scope, compileAndCallJITFunction1(thread_, function, list)); 8071 EXPECT_EQ(*result, NoneType::object()); 8072 EXPECT_TRUE(isIntEqualsWord(list.at(0), 123)); 8073} 8074 8075TEST_F(JitTest, StoreSubscrListWithNonListDeoptimizes) { 8076 if (useCppInterpreter()) { 8077 GTEST_SKIP(); 8078 } 8079 EXPECT_FALSE(runFromCStr(runtime_, R"( 8080class C(list): 8081 pass 8082 8083def foo(obj): 8084 obj[0] = 123 8085 8086# Rewrite STORE_SUBSCR_ANAMORPHIC to STORE_SUBSCR_LIST 8087foo([3, 2, 1]) 8088instance = C([4, 5, 6]) 8089)") 8090 .isError()); 8091 8092 HandleScope scope(thread_); 8093 Function function(&scope, mainModuleAt(runtime_, "foo")); 8094 EXPECT_TRUE(containsBytecode(function, STORE_SUBSCR_LIST)); 8095 void* entry_before = function.entryAsm(); 8096 compileFunction(thread_, function); 8097 EXPECT_NE(function.entryAsm(), entry_before); 8098 List instance(&scope, mainModuleAt(runtime_, "instance")); 8099 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8100 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8101 EXPECT_EQ(function.entryAsm(), entry_before); 8102 EXPECT_EQ(*result, NoneType::object()); 8103 EXPECT_TRUE(isIntEqualsWord(instance.at(0), 123)); 8104} 8105 8106TEST_F(JitTest, InplaceAddSmallintAddsIntegers) { 8107 if (useCppInterpreter()) { 8108 GTEST_SKIP(); 8109 } 8110 EXPECT_FALSE(runFromCStr(runtime_, R"( 8111def foo(obj): 8112 obj += 1 8113 return obj 8114 8115# Rewrite INPLACE_OP_ANAMORPHIC to INPLACE_ADD_SMALLINT 8116foo(1) 8117)") 8118 .isError()); 8119 HandleScope scope(thread_); 8120 Function function(&scope, mainModuleAt(runtime_, "foo")); 8121 EXPECT_TRUE(containsBytecode(function, INPLACE_ADD_SMALLINT)); 8122 Object obj(&scope, SmallInt::fromWord(12)); 8123 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 8124 EXPECT_TRUE(isIntEqualsWord(*result, 13)); 8125} 8126 8127TEST_F(JitTest, InplaceAddSmallintWithNonIntDeoptimizes) { 8128 if (useCppInterpreter()) { 8129 GTEST_SKIP(); 8130 } 8131 EXPECT_FALSE(runFromCStr(runtime_, R"( 8132def foo(left, right): 8133 left += right 8134 return left 8135 8136# Rewrite INPLACE_OP_MONOMORPHIC to INPLACE_ADD_SMALLINT 8137foo(1, 2) 8138)") 8139 .isError()); 8140 8141 HandleScope scope(thread_); 8142 Function function(&scope, mainModuleAt(runtime_, "foo")); 8143 EXPECT_TRUE(containsBytecode(function, INPLACE_ADD_SMALLINT)); 8144 void* entry_before = function.entryAsm(); 8145 compileFunction(thread_, function); 8146 EXPECT_NE(function.entryAsm(), entry_before); 8147 Str left(&scope, SmallStr::fromCStr("hello")); 8148 Str right(&scope, SmallStr::fromCStr(" world")); 8149 Function deopt_caller(&scope, 8150 createTrampolineFunction2(thread_, left, right)); 8151 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8152 EXPECT_EQ(function.entryAsm(), entry_before); 8153 EXPECT_TRUE(isStrEqualsCStr(*result, "hello world")); 8154} 8155 8156TEST_F(JitTest, InplaceSubSmallintSubsIntegers) { 8157 if (useCppInterpreter()) { 8158 GTEST_SKIP(); 8159 } 8160 EXPECT_FALSE(runFromCStr(runtime_, R"( 8161def foo(obj): 8162 obj -= 1 8163 return obj 8164 8165# Rewrite INPLACE_OP_ANAMORPHIC to INPLACE_SUB_SMALLINT 8166foo(1) 8167)") 8168 .isError()); 8169 HandleScope scope(thread_); 8170 Function function(&scope, mainModuleAt(runtime_, "foo")); 8171 EXPECT_TRUE(containsBytecode(function, INPLACE_SUB_SMALLINT)); 8172 Object obj(&scope, SmallInt::fromWord(12)); 8173 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 8174 EXPECT_TRUE(isIntEqualsWord(*result, 11)); 8175} 8176 8177TEST_F(JitTest, InplaceSubSmallintWithNonIntDeoptimizes) { 8178 if (useCppInterpreter()) { 8179 GTEST_SKIP(); 8180 } 8181 EXPECT_FALSE(runFromCStr(runtime_, R"( 8182class C(int): 8183 pass 8184 8185def foo(obj): 8186 obj -= 1 8187 return obj 8188 8189# Rewrite INPLACE_OP_MONOMORPHIC to INPLACE_SUB_SMALLINT 8190foo(1) 8191instance = C(12) 8192)") 8193 .isError()); 8194 8195 HandleScope scope(thread_); 8196 Function function(&scope, mainModuleAt(runtime_, "foo")); 8197 EXPECT_TRUE(containsBytecode(function, INPLACE_SUB_SMALLINT)); 8198 void* entry_before = function.entryAsm(); 8199 compileFunction(thread_, function); 8200 EXPECT_NE(function.entryAsm(), entry_before); 8201 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8202 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8203 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8204 EXPECT_EQ(function.entryAsm(), entry_before); 8205 EXPECT_TRUE(runtime_->isInstanceOfInt(*result)); 8206 EXPECT_TRUE(isIntEqualsWord(intUnderlying(*result), 11)); 8207} 8208 8209TEST_F(JitTest, LoadAttrInstanceWithInstanceReturnsAttribute) { 8210 if (useCppInterpreter()) { 8211 GTEST_SKIP(); 8212 } 8213 EXPECT_FALSE(runFromCStr(runtime_, R"( 8214class C: 8215 def __init__(self, value): 8216 self.foo = value 8217 8218def foo(obj): 8219 return obj.foo 8220 8221# Rewrite LOAD_ATTR_ANAMORPHIC to LOAD_ATTR_INSTANCE 8222foo(C(4)) 8223instance = C(10) 8224)") 8225 .isError()); 8226 HandleScope scope(thread_); 8227 Function function(&scope, mainModuleAt(runtime_, "foo")); 8228 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_INSTANCE)); 8229 Object obj(&scope, mainModuleAt(runtime_, "instance")); 8230 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 8231 EXPECT_TRUE(isIntEqualsWord(*result, 10)); 8232} 8233 8234TEST_F(JitTest, LoadAttrInstanceWithNewTypeDeoptimizes) { 8235 if (useCppInterpreter()) { 8236 GTEST_SKIP(); 8237 } 8238 EXPECT_FALSE(runFromCStr(runtime_, R"( 8239class C: 8240 def __init__(self, value): 8241 self.foo = value 8242 8243class D: 8244 def __init__(self, value): 8245 self.foo = value 8246 8247def foo(obj): 8248 return obj.foo 8249 8250# Rewrite LOAD_ATTR_ANAMORPHIC to LOAD_ATTR_INSTANCE 8251foo(C(4)) 8252instance = D(10) 8253)") 8254 .isError()); 8255 8256 HandleScope scope(thread_); 8257 Function function(&scope, mainModuleAt(runtime_, "foo")); 8258 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_INSTANCE)); 8259 void* entry_before = function.entryAsm(); 8260 compileFunction(thread_, function); 8261 EXPECT_NE(function.entryAsm(), entry_before); 8262 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8263 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8264 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8265 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_POLYMORPHIC)); 8266 EXPECT_TRUE(isIntEqualsWord(*result, 10)); 8267 EXPECT_EQ(function.entryAsm(), entry_before); 8268} 8269 8270TEST_F(JitTest, JumpAbsoluteJumps) { 8271 if (useCppInterpreter()) { 8272 GTEST_SKIP(); 8273 } 8274 HandleScope scope(thread_); 8275 const byte bytecode[] = { 8276 JUMP_ABSOLUTE, 4, // to LOAD_CONST, 1 8277 LOAD_CONST, 0, LOAD_CONST, 1, RETURN_VALUE, 0, 8278 }; 8279 Object none(&scope, NoneType::object()); 8280 Object one(&scope, SmallInt::fromWord(1)); 8281 Tuple consts(&scope, runtime_->newTupleWith2(none, one)); 8282 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8283 8284 Str qualname(&scope, SmallStr::fromCStr("foo")); 8285 Module module(&scope, findMainModule(runtime_)); 8286 Function function( 8287 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8288 moduleAtPutByCStr(thread_, module, "foo", function); 8289 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8290 EXPECT_TRUE(isIntEqualsWord(*result, 1)); 8291} 8292 8293TEST_F(JitTest, JumpForwardJumps) { 8294 if (useCppInterpreter()) { 8295 GTEST_SKIP(); 8296 } 8297 HandleScope scope(thread_); 8298 const byte bytecode[] = { 8299 JUMP_FORWARD, 2, // to LOAD_CONST, 1 8300 LOAD_CONST, 0, LOAD_CONST, 1, RETURN_VALUE, 0, 8301 }; 8302 Object none(&scope, NoneType::object()); 8303 Object one(&scope, SmallInt::fromWord(1)); 8304 Tuple consts(&scope, runtime_->newTupleWith2(none, one)); 8305 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8306 8307 Str qualname(&scope, SmallStr::fromCStr("foo")); 8308 Module module(&scope, findMainModule(runtime_)); 8309 Function function( 8310 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8311 moduleAtPutByCStr(thread_, module, "foo", function); 8312 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8313 EXPECT_TRUE(isIntEqualsWord(*result, 1)); 8314} 8315 8316TEST_F(JitTest, PopJumpIfTrueJumpsIfTrue) { 8317 if (useCppInterpreter()) { 8318 GTEST_SKIP(); 8319 } 8320 HandleScope scope(thread_); 8321 const byte bytecode[] = { 8322 LOAD_CONST, 2, POP_JUMP_IF_TRUE, 8, // to LOAD_CONST, 1 8323 LOAD_CONST, 0, JUMP_FORWARD, 2, // to RETURN_VALUE 8324 LOAD_CONST, 1, RETURN_VALUE, 0, 8325 }; 8326 Object none(&scope, NoneType::object()); 8327 Object one(&scope, SmallInt::fromWord(1)); 8328 Object truthy(&scope, Bool::trueObj()); 8329 Tuple consts(&scope, runtime_->newTupleWith3(none, one, truthy)); 8330 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8331 8332 Str qualname(&scope, SmallStr::fromCStr("foo")); 8333 Module module(&scope, findMainModule(runtime_)); 8334 Function function( 8335 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8336 moduleAtPutByCStr(thread_, module, "foo", function); 8337 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8338 EXPECT_TRUE(isIntEqualsWord(*result, 1)); 8339} 8340 8341TEST_F(JitTest, PopJumpIfTrueJumpsIfTrueNonBool) { 8342 if (useCppInterpreter()) { 8343 GTEST_SKIP(); 8344 } 8345 HandleScope scope(thread_); 8346 const byte bytecode[] = { 8347 LOAD_CONST, 2, POP_JUMP_IF_TRUE, 8, // to LOAD_CONST, 1 8348 LOAD_CONST, 0, JUMP_FORWARD, 2, // to RETURN_VALUE 8349 LOAD_CONST, 1, RETURN_VALUE, 0, 8350 }; 8351 Object none(&scope, NoneType::object()); 8352 Object one(&scope, SmallInt::fromWord(1)); 8353 Object truthy(&scope, runtime_->newTupleWith1(one)); 8354 Tuple consts(&scope, runtime_->newTupleWith3(none, one, truthy)); 8355 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8356 8357 Str qualname(&scope, SmallStr::fromCStr("foo")); 8358 Module module(&scope, findMainModule(runtime_)); 8359 Function function( 8360 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8361 moduleAtPutByCStr(thread_, module, "foo", function); 8362 Function caller(&scope, createTrampolineFunction(thread_)); 8363 compileFunction(thread_, function); 8364 Object result(&scope, Interpreter::call0(thread_, caller)); 8365 EXPECT_TRUE(isIntEqualsWord(*result, 1)); 8366} 8367 8368TEST_F(JitTest, PopJumpIfTrueDoesNotJumpIfFalse) { 8369 if (useCppInterpreter()) { 8370 GTEST_SKIP(); 8371 } 8372 HandleScope scope(thread_); 8373 const byte bytecode[] = { 8374 LOAD_CONST, 2, POP_JUMP_IF_TRUE, 8, // to LOAD_CONST, 1 8375 LOAD_CONST, 0, JUMP_FORWARD, 2, // to RETURN_VALUE 8376 LOAD_CONST, 1, RETURN_VALUE, 0, 8377 }; 8378 Object none(&scope, NoneType::object()); 8379 Object one(&scope, SmallInt::fromWord(1)); 8380 Object falsy(&scope, Bool::falseObj()); 8381 Tuple consts(&scope, runtime_->newTupleWith3(none, one, falsy)); 8382 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8383 8384 Str qualname(&scope, SmallStr::fromCStr("foo")); 8385 Module module(&scope, findMainModule(runtime_)); 8386 Function function( 8387 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8388 moduleAtPutByCStr(thread_, module, "foo", function); 8389 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8390 EXPECT_EQ(*result, NoneType::object()); 8391} 8392 8393TEST_F(JitTest, PopJumpIfFalseJumpsIfFalse) { 8394 if (useCppInterpreter()) { 8395 GTEST_SKIP(); 8396 } 8397 HandleScope scope(thread_); 8398 const byte bytecode[] = { 8399 LOAD_CONST, 2, POP_JUMP_IF_FALSE, 8, // to LOAD_CONST, 1 8400 LOAD_CONST, 0, JUMP_FORWARD, 2, // to RETURN_VALUE 8401 LOAD_CONST, 1, RETURN_VALUE, 0, 8402 }; 8403 Object none(&scope, NoneType::object()); 8404 Object one(&scope, SmallInt::fromWord(1)); 8405 Object falsy(&scope, Bool::falseObj()); 8406 Tuple consts(&scope, runtime_->newTupleWith3(none, one, falsy)); 8407 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8408 8409 Str qualname(&scope, SmallStr::fromCStr("foo")); 8410 Module module(&scope, findMainModule(runtime_)); 8411 Function function( 8412 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8413 moduleAtPutByCStr(thread_, module, "foo", function); 8414 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8415 EXPECT_TRUE(isIntEqualsWord(*result, 1)); 8416} 8417 8418TEST_F(JitTest, PopJumpIfFalseDoesNotJumpIfTrue) { 8419 if (useCppInterpreter()) { 8420 GTEST_SKIP(); 8421 } 8422 HandleScope scope(thread_); 8423 const byte bytecode[] = { 8424 LOAD_CONST, 2, POP_JUMP_IF_FALSE, 8, // to LOAD_CONST, 1 8425 LOAD_CONST, 0, JUMP_FORWARD, 2, // to RETURN_VALUE 8426 LOAD_CONST, 1, RETURN_VALUE, 0, 8427 }; 8428 Object none(&scope, NoneType::object()); 8429 Object one(&scope, SmallInt::fromWord(1)); 8430 Object truthy(&scope, Bool::trueObj()); 8431 Tuple consts(&scope, runtime_->newTupleWith3(none, one, truthy)); 8432 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8433 8434 Str qualname(&scope, SmallStr::fromCStr("foo")); 8435 Module module(&scope, findMainModule(runtime_)); 8436 Function function( 8437 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8438 moduleAtPutByCStr(thread_, module, "foo", function); 8439 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8440 EXPECT_EQ(*result, NoneType::object()); 8441} 8442 8443TEST_F(JitTest, JumpIfTrueOrPopJumpsIfTrue) { 8444 if (useCppInterpreter()) { 8445 GTEST_SKIP(); 8446 } 8447 HandleScope scope(thread_); 8448 const byte bytecode[] = { 8449 LOAD_CONST, 1, JUMP_IF_TRUE_OR_POP, 6, // to RETURN_VALUE 8450 LOAD_CONST, 0, RETURN_VALUE, 0, 8451 }; 8452 Object none(&scope, NoneType::object()); 8453 Object truthy(&scope, Bool::trueObj()); 8454 Tuple consts(&scope, runtime_->newTupleWith2(none, truthy)); 8455 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8456 8457 Str qualname(&scope, SmallStr::fromCStr("foo")); 8458 Module module(&scope, findMainModule(runtime_)); 8459 Function function( 8460 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8461 moduleAtPutByCStr(thread_, module, "foo", function); 8462 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8463 EXPECT_EQ(*result, Bool::trueObj()); 8464} 8465 8466TEST_F(JitTest, JumpIfTrueOrPopPopsIfFalse) { 8467 if (useCppInterpreter()) { 8468 GTEST_SKIP(); 8469 } 8470 HandleScope scope(thread_); 8471 const byte bytecode[] = { 8472 LOAD_CONST, 1, JUMP_IF_TRUE_OR_POP, 6, // to RETURN_VALUE 8473 LOAD_CONST, 0, RETURN_VALUE, 0, 8474 }; 8475 Object none(&scope, NoneType::object()); 8476 Object falsy(&scope, Bool::falseObj()); 8477 Tuple consts(&scope, runtime_->newTupleWith2(none, falsy)); 8478 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8479 8480 Str qualname(&scope, SmallStr::fromCStr("foo")); 8481 Module module(&scope, findMainModule(runtime_)); 8482 Function function( 8483 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8484 moduleAtPutByCStr(thread_, module, "foo", function); 8485 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8486 EXPECT_EQ(*result, NoneType::object()); 8487} 8488 8489TEST_F(JitTest, JumpIfFalseOrPopJumpsIfFalse) { 8490 if (useCppInterpreter()) { 8491 GTEST_SKIP(); 8492 } 8493 HandleScope scope(thread_); 8494 const byte bytecode[] = { 8495 LOAD_CONST, 1, JUMP_IF_FALSE_OR_POP, 6, // to RETURN_VALUE 8496 LOAD_CONST, 0, RETURN_VALUE, 0, 8497 }; 8498 Object none(&scope, NoneType::object()); 8499 Object falsy(&scope, Bool::falseObj()); 8500 Tuple consts(&scope, runtime_->newTupleWith2(none, falsy)); 8501 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8502 8503 Str qualname(&scope, SmallStr::fromCStr("foo")); 8504 Module module(&scope, findMainModule(runtime_)); 8505 Function function( 8506 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8507 moduleAtPutByCStr(thread_, module, "foo", function); 8508 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8509 EXPECT_EQ(*result, Bool::falseObj()); 8510} 8511 8512TEST_F(JitTest, JumpIfFalseOrPopPopsIfTrue) { 8513 if (useCppInterpreter()) { 8514 GTEST_SKIP(); 8515 } 8516 HandleScope scope(thread_); 8517 const byte bytecode[] = { 8518 LOAD_CONST, 1, JUMP_IF_FALSE_OR_POP, 6, // to RETURN_VALUE 8519 LOAD_CONST, 0, RETURN_VALUE, 0, 8520 }; 8521 Object none(&scope, NoneType::object()); 8522 Object truthy(&scope, Bool::trueObj()); 8523 Tuple consts(&scope, runtime_->newTupleWith2(none, truthy)); 8524 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 8525 8526 Str qualname(&scope, SmallStr::fromCStr("foo")); 8527 Module module(&scope, findMainModule(runtime_)); 8528 Function function( 8529 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 8530 moduleAtPutByCStr(thread_, module, "foo", function); 8531 Object result(&scope, compileAndCallJITFunction(thread_, function)); 8532 EXPECT_EQ(*result, NoneType::object()); 8533} 8534 8535TEST_F(JitTest, ForIterListIteratesOverList) { 8536 if (useCppInterpreter()) { 8537 GTEST_SKIP(); 8538 } 8539 EXPECT_FALSE(runFromCStr(runtime_, R"( 8540def foo(obj): 8541 result = 0 8542 for item in obj: 8543 result += item 8544 return result 8545 8546# Rewrite FOR_ITER_ANAMORPHIC with FOR_ITER_LIST 8547foo([1, 2, 3]) 8548instance = [4, 5, 6] 8549)") 8550 .isError()); 8551 HandleScope scope(thread_); 8552 Function function(&scope, mainModuleAt(runtime_, "foo")); 8553 EXPECT_TRUE(containsBytecode(function, FOR_ITER_LIST)); 8554 List list(&scope, mainModuleAt(runtime_, "instance")); 8555 Object result(&scope, compileAndCallJITFunction1(thread_, function, list)); 8556 EXPECT_TRUE(isIntEqualsWord(*result, 15)); 8557} 8558 8559TEST_F(JitTest, ForIterListWithNonListDeoptimizes) { 8560 if (useCppInterpreter()) { 8561 GTEST_SKIP(); 8562 } 8563 EXPECT_FALSE(runFromCStr(runtime_, R"( 8564class D: 8565 def __next__(self): 8566 raise StopIteration 8567 8568class C: 8569 def __iter__(self): 8570 return D() 8571 8572def foo(obj): 8573 result = 0 8574 for item in obj: 8575 result += item 8576 return result 8577 8578# Rewrite FOR_ITER_ANAMORPHIC to FOR_ITER_LIST 8579foo([1, 2, 3]) 8580instance = C() 8581)") 8582 .isError()); 8583 8584 HandleScope scope(thread_); 8585 Function function(&scope, mainModuleAt(runtime_, "foo")); 8586 EXPECT_TRUE(containsBytecode(function, FOR_ITER_LIST)); 8587 void* entry_before = function.entryAsm(); 8588 compileFunction(thread_, function); 8589 EXPECT_NE(function.entryAsm(), entry_before); 8590 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8591 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8592 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8593 EXPECT_TRUE(containsBytecode(function, FOR_ITER_MONOMORPHIC)); 8594 EXPECT_TRUE(isIntEqualsWord(*result, 0)); 8595 EXPECT_EQ(function.entryAsm(), entry_before); 8596} 8597 8598TEST_F(JitTest, ForIterRangeIteratesOverRange) { 8599 if (useCppInterpreter()) { 8600 GTEST_SKIP(); 8601 } 8602 EXPECT_FALSE(runFromCStr(runtime_, R"( 8603def foo(obj): 8604 result = 0 8605 for item in obj: 8606 result += item 8607 return result 8608 8609# Rewrite FOR_ITER_ANAMORPHIC with FOR_ITER_RANGE 8610foo(range(1, 4)) 8611instance = range(4, 7) 8612)") 8613 .isError()); 8614 HandleScope scope(thread_); 8615 Function function(&scope, mainModuleAt(runtime_, "foo")); 8616 EXPECT_TRUE(containsBytecode(function, FOR_ITER_RANGE)); 8617 Range range(&scope, mainModuleAt(runtime_, "instance")); 8618 Object result(&scope, compileAndCallJITFunction1(thread_, function, range)); 8619 EXPECT_TRUE(isIntEqualsWord(*result, 15)); 8620} 8621 8622TEST_F(JitTest, ForIterRangeWithNonRangeDeoptimizes) { 8623 if (useCppInterpreter()) { 8624 GTEST_SKIP(); 8625 } 8626 EXPECT_FALSE(runFromCStr(runtime_, R"( 8627class D: 8628 def __next__(self): 8629 raise StopIteration 8630 8631class C: 8632 def __iter__(self): 8633 return D() 8634 8635def foo(obj): 8636 result = 0 8637 for item in obj: 8638 result += item 8639 return result 8640 8641# Rewrite FOR_ITER_ANAMORPHIC to FOR_ITER_RANGE 8642foo(range(1, 4)) 8643instance = C() 8644)") 8645 .isError()); 8646 8647 HandleScope scope(thread_); 8648 Function function(&scope, mainModuleAt(runtime_, "foo")); 8649 EXPECT_TRUE(containsBytecode(function, FOR_ITER_RANGE)); 8650 void* entry_before = function.entryAsm(); 8651 compileFunction(thread_, function); 8652 EXPECT_NE(function.entryAsm(), entry_before); 8653 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8654 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8655 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8656 EXPECT_TRUE(containsBytecode(function, FOR_ITER_MONOMORPHIC)); 8657 EXPECT_TRUE(isIntEqualsWord(*result, 0)); 8658 EXPECT_EQ(function.entryAsm(), entry_before); 8659} 8660 8661TEST_F(JitTest, LoadAttrInstanceTypeBoundMethodWithInstanceReturnsBoundMethod) { 8662 if (useCppInterpreter()) { 8663 GTEST_SKIP(); 8664 } 8665 EXPECT_FALSE(runFromCStr(runtime_, R"( 8666class C: 8667 def foo(self): 8668 pass 8669 8670def foo(obj): 8671 return obj.foo 8672 8673# Rewrite LOAD_ATTR_ANAMORPHIC to LOAD_ATTR_INSTANCE_TYPE_BOUND_METHOD 8674foo(C()) 8675instance = C() 8676)") 8677 .isError()); 8678 HandleScope scope(thread_); 8679 Function function(&scope, mainModuleAt(runtime_, "foo")); 8680 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_INSTANCE_TYPE_BOUND_METHOD)); 8681 Object obj(&scope, mainModuleAt(runtime_, "instance")); 8682 Object result_obj(&scope, compileAndCallJITFunction1(thread_, function, obj)); 8683 ASSERT_TRUE(result_obj.isBoundMethod()); 8684 BoundMethod result(&scope, *result_obj); 8685 EXPECT_EQ(result.self(), *obj); 8686} 8687 8688TEST_F(JitTest, LoadAttrInstanceTypeBoundMethodWithNewTypeDeoptimizes) { 8689 if (useCppInterpreter()) { 8690 GTEST_SKIP(); 8691 } 8692 EXPECT_FALSE(runFromCStr(runtime_, R"( 8693class C: 8694 def foo(self): 8695 pass 8696 8697class D: 8698 def foo(self): 8699 pass 8700 8701def foo(obj): 8702 return obj.foo 8703 8704# Rewrite LOAD_ATTR_ANAMORPHIC to LOAD_ATTR_INSTANCE_TYPE_BOUND_METHOD 8705foo(C()) 8706instance = D() 8707)") 8708 .isError()); 8709 8710 HandleScope scope(thread_); 8711 Function function(&scope, mainModuleAt(runtime_, "foo")); 8712 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_INSTANCE_TYPE_BOUND_METHOD)); 8713 void* entry_before = function.entryAsm(); 8714 compileFunction(thread_, function); 8715 EXPECT_NE(function.entryAsm(), entry_before); 8716 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8717 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8718 Object result_obj(&scope, Interpreter::call0(thread_, deopt_caller)); 8719 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_POLYMORPHIC)); 8720 ASSERT_TRUE(result_obj.isBoundMethod()); 8721 BoundMethod result(&scope, *result_obj); 8722 EXPECT_EQ(result.self(), *instance); 8723 EXPECT_EQ(function.entryAsm(), entry_before); 8724} 8725 8726TEST_F(JitTest, LoadAttrPolymorphicWithCacheHitReturnsAttribute) { 8727 if (useCppInterpreter()) { 8728 GTEST_SKIP(); 8729 } 8730 EXPECT_FALSE(runFromCStr(runtime_, R"( 8731class C: 8732 def __init__(self, value): 8733 self.value = value 8734 8735class D(C): 8736 pass 8737 8738def foo(obj): 8739 return obj.value 8740 8741# Rewrite LOAD_ATTR_ANAMORPHIC to LOAD_ATTR_INSTANCE 8742foo(C(1)) 8743# Rewrite LOAD_ATTR_INSTANCE to LOAD_ATTR_POLYMORPHIC 8744foo(D(2)) 8745instance = C(3) 8746)") 8747 .isError()); 8748 HandleScope scope(thread_); 8749 Function function(&scope, mainModuleAt(runtime_, "foo")); 8750 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_POLYMORPHIC)); 8751 Object obj(&scope, mainModuleAt(runtime_, "instance")); 8752 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 8753 EXPECT_TRUE(isIntEqualsWord(*result, 3)); 8754} 8755 8756TEST_F(JitTest, LoadAttrPolymorphicWithCacheMissReturnsAttribute) { 8757 if (useCppInterpreter()) { 8758 GTEST_SKIP(); 8759 } 8760 EXPECT_FALSE(runFromCStr(runtime_, R"( 8761class C: 8762 def __init__(self, value): 8763 self.value = value 8764 8765class D(C): 8766 pass 8767 8768class E(C): 8769 pass 8770 8771def foo(obj): 8772 return obj.value 8773 8774# Rewrite LOAD_ATTR_ANAMORPHIC to LOAD_ATTR_INSTANCE 8775foo(C(1)) 8776# Rewrite LOAD_ATTR_INSTANCE to LOAD_ATTR_POLYMORPHIC 8777foo(D(2)) 8778instance = E(3) 8779)") 8780 .isError()); 8781 HandleScope scope(thread_); 8782 Function function(&scope, mainModuleAt(runtime_, "foo")); 8783 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_POLYMORPHIC)); 8784 compileFunction(thread_, function); 8785 // Can't use compileAndCallJITFunction1 because the doLoadAttrPolymorphic 8786 // fallback needs to read the cache index off the bytecode. 8787 void* entry_jit = function.entryAsm(); 8788 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8789 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8790 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8791 EXPECT_TRUE(containsBytecode(function, LOAD_ATTR_POLYMORPHIC)); 8792 EXPECT_TRUE(isIntEqualsWord(*result, 3)); 8793 EXPECT_NE(function.entryAsm(), entry_jit); 8794} 8795 8796TEST_F(JitTest, StoreAttrInstanceWithInstanceStoresAttribute) { 8797 if (useCppInterpreter()) { 8798 GTEST_SKIP(); 8799 } 8800 EXPECT_FALSE(runFromCStr(runtime_, R"( 8801class C: 8802 def __init__(self, value): 8803 self.foo = value 8804 8805def foo(obj): 8806 obj.foo = 17 8807 return obj.foo 8808 8809# Rewrite STORE_ATTR_ANAMORPHIC to STORE_ATTR_INSTANCE 8810foo(C(4)) 8811instance = C(10) 8812)") 8813 .isError()); 8814 HandleScope scope(thread_); 8815 Function function(&scope, mainModuleAt(runtime_, "foo")); 8816 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_INSTANCE)); 8817 Object obj(&scope, mainModuleAt(runtime_, "instance")); 8818 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 8819 EXPECT_TRUE(isIntEqualsWord(*result, 17)); 8820} 8821 8822TEST_F(JitTest, StoreAttrInstanceWithNewTypeDeoptimizes) { 8823 if (useCppInterpreter()) { 8824 GTEST_SKIP(); 8825 } 8826 EXPECT_FALSE(runFromCStr(runtime_, R"( 8827class C: 8828 def __init__(self, value): 8829 self.foo = value 8830 8831class D: 8832 def __init__(self, value): 8833 self.foo = value 8834 8835def foo(obj): 8836 obj.foo = 17 8837 return obj.foo 8838 8839# Rewrite STORE_ATTR_ANAMORPHIC to STORE_ATTR_INSTANCE 8840foo(C(4)) 8841instance = D(10) 8842)") 8843 .isError()); 8844 8845 HandleScope scope(thread_); 8846 Function function(&scope, mainModuleAt(runtime_, "foo")); 8847 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_INSTANCE)); 8848 void* entry_before = function.entryAsm(); 8849 compileFunction(thread_, function); 8850 EXPECT_NE(function.entryAsm(), entry_before); 8851 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8852 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8853 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8854 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_POLYMORPHIC)); 8855 EXPECT_TRUE(isIntEqualsWord(*result, 17)); 8856 EXPECT_EQ(function.entryAsm(), entry_before); 8857} 8858 8859TEST_F(JitTest, StoreAttrPolymorphicWithCacheHitReturnsAttribute) { 8860 if (useCppInterpreter()) { 8861 GTEST_SKIP(); 8862 } 8863 EXPECT_FALSE(runFromCStr(runtime_, R"( 8864class C: 8865 def __init__(self, value): 8866 self.value = value 8867 8868class D(C): 8869 pass 8870 8871def foo(obj): 8872 obj.value = 17 8873 return obj.value 8874 8875# Rewrite STORE_ATTR_ANAMORPHIC to STORE_ATTR_INSTANCE 8876foo(C(1)) 8877# Rewrite STORE_ATTR_INSTANCE to STORE_ATTR_POLYMORPHIC 8878foo(D(2)) 8879instance = C(3) 8880)") 8881 .isError()); 8882 HandleScope scope(thread_); 8883 Function function(&scope, mainModuleAt(runtime_, "foo")); 8884 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_POLYMORPHIC)); 8885 Object obj(&scope, mainModuleAt(runtime_, "instance")); 8886 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 8887 EXPECT_TRUE(isIntEqualsWord(*result, 17)); 8888} 8889 8890TEST_F(JitTest, StoreAttrPolymorphicWithCacheMissReturnsAttribute) { 8891 if (useCppInterpreter()) { 8892 GTEST_SKIP(); 8893 } 8894 EXPECT_FALSE(runFromCStr(runtime_, R"( 8895class C: 8896 def __init__(self, value): 8897 self.value = value 8898 8899class D(C): 8900 pass 8901 8902class E(C): 8903 pass 8904 8905def foo(obj): 8906 obj.value = 17 8907 return obj.value 8908 8909# Rewrite STORE_ATTR_ANAMORPHIC to STORE_ATTR_INSTANCE 8910foo(C(1)) 8911# Rewrite STORE_ATTR_INSTANCE to STORE_ATTR_POLYMORPHIC 8912foo(D(2)) 8913instance = E(3) 8914)") 8915 .isError()); 8916 HandleScope scope(thread_); 8917 Function function(&scope, mainModuleAt(runtime_, "foo")); 8918 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_POLYMORPHIC)); 8919 compileFunction(thread_, function); 8920 // Can't use compileAndCallJITFunction1 because the doStoreAttrPolymorphic 8921 // fallback needs to read the cache index off the bytecode. 8922 void* entry_jit = function.entryAsm(); 8923 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8924 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8925 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8926 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_POLYMORPHIC)); 8927 EXPECT_TRUE(isIntEqualsWord(*result, 17)); 8928 EXPECT_NE(function.entryAsm(), entry_jit); 8929} 8930 8931TEST_F(JitTest, StoreAttrInstanceOverflowWithInstanceStoresAttribute) { 8932 if (useCppInterpreter()) { 8933 GTEST_SKIP(); 8934 } 8935 EXPECT_FALSE(runFromCStr(runtime_, R"( 8936class C: 8937 pass 8938 8939def foo(obj): 8940 obj.foo = 17 8941 return obj.foo 8942 8943# Rewrite STORE_ATTR_ANAMORPHIC to STORE_ATTR_INSTANCE_OVERFLOW 8944obj1 = C() 8945obj1.foo = 1 8946foo(obj1) 8947instance = C() 8948instance.foo = 1 8949)") 8950 .isError()); 8951 HandleScope scope(thread_); 8952 Function function(&scope, mainModuleAt(runtime_, "foo")); 8953 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_INSTANCE_OVERFLOW)); 8954 Object obj(&scope, mainModuleAt(runtime_, "instance")); 8955 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 8956 EXPECT_TRUE(isIntEqualsWord(*result, 17)); 8957} 8958 8959TEST_F(JitTest, StoreAttrInstanceOverflowWithNewTypeDeoptimizes) { 8960 if (useCppInterpreter()) { 8961 GTEST_SKIP(); 8962 } 8963 EXPECT_FALSE(runFromCStr(runtime_, R"( 8964class C: 8965 pass 8966 8967class D: 8968 pass 8969 8970def foo(obj): 8971 obj.foo = 17 8972 return obj.foo 8973 8974# Rewrite STORE_ATTR_ANAMORPHIC to STORE_ATTR_INSTANCE_OVERFLOW 8975obj1 = C() 8976obj1.foo = 1 8977foo(obj1) 8978instance = D() 8979instance.foo = 2 8980)") 8981 .isError()); 8982 8983 HandleScope scope(thread_); 8984 Function function(&scope, mainModuleAt(runtime_, "foo")); 8985 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_INSTANCE_OVERFLOW)); 8986 void* entry_before = function.entryAsm(); 8987 compileFunction(thread_, function); 8988 EXPECT_NE(function.entryAsm(), entry_before); 8989 Object instance(&scope, mainModuleAt(runtime_, "instance")); 8990 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 8991 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 8992 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_POLYMORPHIC)); 8993 EXPECT_TRUE(isIntEqualsWord(*result, 17)); 8994 EXPECT_EQ(function.entryAsm(), entry_before); 8995} 8996 8997TEST_F(JitTest, BuildListReturnsList) { 8998 if (useCppInterpreter()) { 8999 GTEST_SKIP(); 9000 } 9001 EXPECT_FALSE(runFromCStr(runtime_, R"( 9002def foo(): 9003 return [1, 2, 3] 9004)") 9005 .isError()); 9006 HandleScope scope(thread_); 9007 Function function(&scope, mainModuleAt(runtime_, "foo")); 9008 EXPECT_TRUE(containsBytecode(function, BUILD_LIST)); 9009 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9010 EXPECT_PYLIST_EQ(result, {1, 2, 3}); 9011} 9012 9013TEST_F(JitTest, BuildListUnpackReturnsList) { 9014 if (useCppInterpreter()) { 9015 GTEST_SKIP(); 9016 } 9017 EXPECT_FALSE(runFromCStr(runtime_, R"( 9018def foo(): 9019 a = [2, 3] 9020 return [1, *a] 9021)") 9022 .isError()); 9023 HandleScope scope(thread_); 9024 Function function(&scope, mainModuleAt(runtime_, "foo")); 9025 EXPECT_TRUE(containsBytecode(function, BUILD_LIST_UNPACK)); 9026 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9027 EXPECT_PYLIST_EQ(result, {1, 2, 3}); 9028} 9029 9030TEST_F(JitTest, BuildMapReturnsDict) { 9031 if (useCppInterpreter()) { 9032 GTEST_SKIP(); 9033 } 9034 EXPECT_FALSE(runFromCStr(runtime_, R"( 9035def foo(): 9036 return {"hello": "world"} 9037)") 9038 .isError()); 9039 HandleScope scope(thread_); 9040 Function function(&scope, mainModuleAt(runtime_, "foo")); 9041 EXPECT_TRUE(containsBytecode(function, BUILD_MAP)); 9042 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9043 ASSERT_TRUE(result.isDict()); 9044 EXPECT_EQ(Dict::cast(*result).numItems(), 1); 9045} 9046 9047TEST_F(JitTest, BuildMapUnpackReturnsDict) { 9048 if (useCppInterpreter()) { 9049 GTEST_SKIP(); 9050 } 9051 EXPECT_FALSE(runFromCStr(runtime_, R"( 9052def foo(): 9053 a = {"goodbye": "world"} 9054 return {"hello": "world", **a} 9055)") 9056 .isError()); 9057 HandleScope scope(thread_); 9058 Function function(&scope, mainModuleAt(runtime_, "foo")); 9059 EXPECT_TRUE(containsBytecode(function, BUILD_MAP_UNPACK)); 9060 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9061 ASSERT_TRUE(result.isDict()); 9062 EXPECT_EQ(Dict::cast(*result).numItems(), 2); 9063} 9064 9065TEST_F(JitTest, BuildSetReturnsSet) { 9066 if (useCppInterpreter()) { 9067 GTEST_SKIP(); 9068 } 9069 EXPECT_FALSE(runFromCStr(runtime_, R"( 9070def foo(): 9071 return {"hello", "world"} 9072)") 9073 .isError()); 9074 HandleScope scope(thread_); 9075 Function function(&scope, mainModuleAt(runtime_, "foo")); 9076 EXPECT_TRUE(containsBytecode(function, BUILD_SET)); 9077 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9078 ASSERT_TRUE(result.isSet()); 9079 EXPECT_EQ(Set::cast(*result).numItems(), 2); 9080} 9081 9082TEST_F(JitTest, BuildSetUnpackReturnsSet) { 9083 if (useCppInterpreter()) { 9084 GTEST_SKIP(); 9085 } 9086 EXPECT_FALSE(runFromCStr(runtime_, R"( 9087def foo(): 9088 a = {"goodbye", "world"} 9089 return {"hello", "world", *a} 9090)") 9091 .isError()); 9092 HandleScope scope(thread_); 9093 Function function(&scope, mainModuleAt(runtime_, "foo")); 9094 EXPECT_TRUE(containsBytecode(function, BUILD_SET_UNPACK)); 9095 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9096 ASSERT_TRUE(result.isSet()); 9097 EXPECT_EQ(Set::cast(*result).numItems(), 3); 9098} 9099 9100TEST_F(JitTest, BuildTupleReturnsTuple) { 9101 if (useCppInterpreter()) { 9102 GTEST_SKIP(); 9103 } 9104 EXPECT_FALSE(runFromCStr(runtime_, R"( 9105def foo(): 9106 a = 1 9107 return (a, 2) 9108)") 9109 .isError()); 9110 HandleScope scope(thread_); 9111 Function function(&scope, mainModuleAt(runtime_, "foo")); 9112 EXPECT_TRUE(containsBytecode(function, BUILD_TUPLE)); 9113 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9114 ASSERT_TRUE(result.isTuple()); 9115 EXPECT_EQ(Tuple::cast(*result).length(), 2); 9116} 9117 9118TEST_F(JitTest, BuildTupleUnpackReturnsTuple) { 9119 if (useCppInterpreter()) { 9120 GTEST_SKIP(); 9121 } 9122 EXPECT_FALSE(runFromCStr(runtime_, R"( 9123def foo(): 9124 a = (2, 3) 9125 return (1, *a) 9126)") 9127 .isError()); 9128 HandleScope scope(thread_); 9129 Function function(&scope, mainModuleAt(runtime_, "foo")); 9130 EXPECT_TRUE(containsBytecode(function, BUILD_TUPLE_UNPACK)); 9131 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9132 ASSERT_TRUE(result.isTuple()); 9133 EXPECT_EQ(Tuple::cast(*result).length(), 3); 9134} 9135 9136TEST_F(JitTest, BuildStringReturnsString) { 9137 if (useCppInterpreter()) { 9138 GTEST_SKIP(); 9139 } 9140 HandleScope scope(thread_); 9141 const byte bytecode[] = { 9142 LOAD_CONST, 0, LOAD_CONST, 1, BUILD_STRING, 2, RETURN_VALUE, 0, 9143 }; 9144 Object left(&scope, SmallStr::fromCStr("hello")); 9145 Object right(&scope, SmallStr::fromCStr(" world")); 9146 Tuple consts(&scope, runtime_->newTupleWith2(left, right)); 9147 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 9148 9149 Str qualname(&scope, SmallStr::fromCStr("foo")); 9150 Module module(&scope, findMainModule(runtime_)); 9151 Function function( 9152 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 9153 moduleAtPutByCStr(thread_, module, "foo", function); 9154 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9155 EXPECT_TRUE(isStrEqualsCStr(*result, "hello world")); 9156} 9157 9158TEST_F(JitTest, FormatValueReturnsString) { 9159 if (useCppInterpreter()) { 9160 GTEST_SKIP(); 9161 } 9162 EXPECT_FALSE(runFromCStr(runtime_, R"( 9163def foo(obj): 9164 return f"foo{obj}bar" 9165)") 9166 .isError()); 9167 HandleScope scope(thread_); 9168 Function function(&scope, mainModuleAt(runtime_, "foo")); 9169 EXPECT_TRUE(containsBytecode(function, FORMAT_VALUE)); 9170 Object obj(&scope, SmallInt::fromWord(123)); 9171 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 9172 EXPECT_TRUE(isStrEqualsCStr(*result, "foo123bar")); 9173} 9174 9175TEST_F(JitTest, DupTopTwoDuplicatesTwoTwoStackElements) { 9176 if (useCppInterpreter()) { 9177 GTEST_SKIP(); 9178 } 9179 HandleScope scope(thread_); 9180 byte bytecode[] = { 9181 LOAD_CONST, 0, LOAD_CONST, 1, DUP_TOP_TWO, 0, 9182 BUILD_LIST, 4, RETURN_VALUE, 0, 9183 }; 9184 Object left(&scope, SmallInt::fromWord(1)); 9185 Object right(&scope, SmallInt::fromWord(2)); 9186 Tuple consts(&scope, runtime_->newTupleWith2(left, right)); 9187 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 9188 9189 Str qualname(&scope, SmallStr::fromCStr("foo")); 9190 Module module(&scope, findMainModule(runtime_)); 9191 Function function( 9192 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 9193 moduleAtPutByCStr(thread_, module, "foo", function); 9194 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9195 EXPECT_PYLIST_EQ(result, {1, 2, 1, 2}); 9196} 9197 9198TEST_F(JitTest, RotFourRotatesStackElements) { 9199 if (useCppInterpreter()) { 9200 GTEST_SKIP(); 9201 } 9202 HandleScope scope(thread_); 9203 const byte bytecode[] = { 9204 LOAD_CONST, 0, LOAD_CONST, 1, LOAD_CONST, 2, LOAD_CONST, 3, 9205 ROT_FOUR, 0, BUILD_LIST, 4, RETURN_VALUE, 0, 9206 }; 9207 Object obj1(&scope, SmallInt::fromWord(1)); 9208 Object obj2(&scope, SmallInt::fromWord(2)); 9209 Object obj3(&scope, SmallInt::fromWord(3)); 9210 Object obj4(&scope, SmallInt::fromWord(4)); 9211 Tuple consts(&scope, runtime_->newTupleWith4(obj1, obj2, obj3, obj4)); 9212 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 9213 9214 Str qualname(&scope, SmallStr::fromCStr("foo")); 9215 Module module(&scope, findMainModule(runtime_)); 9216 Function function( 9217 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 9218 moduleAtPutByCStr(thread_, module, "foo", function); 9219 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9220 EXPECT_PYLIST_EQ(result, {4, 1, 2, 3}); 9221} 9222 9223TEST_F(JitTest, RotThreeRotatesStackElements) { 9224 if (useCppInterpreter()) { 9225 GTEST_SKIP(); 9226 } 9227 HandleScope scope(thread_); 9228 const byte bytecode[] = { 9229 LOAD_CONST, 0, LOAD_CONST, 1, LOAD_CONST, 2, 9230 ROT_THREE, 0, BUILD_LIST, 3, RETURN_VALUE, 0, 9231 }; 9232 Object obj1(&scope, SmallInt::fromWord(1)); 9233 Object obj2(&scope, SmallInt::fromWord(2)); 9234 Object obj3(&scope, SmallInt::fromWord(3)); 9235 Tuple consts(&scope, runtime_->newTupleWith3(obj1, obj2, obj3)); 9236 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 9237 9238 Str qualname(&scope, SmallStr::fromCStr("foo")); 9239 Module module(&scope, findMainModule(runtime_)); 9240 Function function( 9241 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module)); 9242 moduleAtPutByCStr(thread_, module, "foo", function); 9243 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9244 EXPECT_PYLIST_EQ(result, {3, 1, 2}); 9245} 9246 9247TEST_F(JitTest, UnaryNegativeCallsDunderNeg) { 9248 if (useCppInterpreter()) { 9249 GTEST_SKIP(); 9250 } 9251 ASSERT_FALSE(runFromCStr(runtime_, R"( 9252class C: 9253 def __neg__(self): 9254 return 5 9255def foo(obj): 9256 return -obj 9257instance = C() 9258foo(instance) # Change UNARY_OP_ANAMORPHIC to UNARY_NEGATIVE 9259)") 9260 .isError()); 9261 HandleScope scope(thread_); 9262 Function function(&scope, mainModuleAt(runtime_, "foo")); 9263 EXPECT_TRUE(containsBytecode(function, UNARY_NEGATIVE)); 9264 Object obj(&scope, mainModuleAt(runtime_, "instance")); 9265 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 9266 EXPECT_TRUE(isIntEqualsWord(*result, 5)); 9267} 9268 9269TEST_F(JitTest, UnaryNegativeSmallIntWithPositiveReturnsNegative) { 9270 if (useCppInterpreter()) { 9271 GTEST_SKIP(); 9272 } 9273 ASSERT_FALSE(runFromCStr(runtime_, R"( 9274def foo(obj): 9275 return -obj 9276foo(0) # Change UNARY_OP_ANAMORPHIC to UNARY_NEGATIVE_SMALLINT 9277)") 9278 .isError()); 9279 HandleScope scope(thread_); 9280 Function function(&scope, mainModuleAt(runtime_, "foo")); 9281 EXPECT_TRUE(containsBytecode(function, UNARY_NEGATIVE_SMALLINT)); 9282 Object obj(&scope, SmallInt::fromWord(123)); 9283 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 9284 EXPECT_TRUE(isIntEqualsWord(*result, -123)); 9285} 9286 9287TEST_F(JitTest, UnaryNegativeSmallIntWithNegativeReturnsPositive) { 9288 if (useCppInterpreter()) { 9289 GTEST_SKIP(); 9290 } 9291 ASSERT_FALSE(runFromCStr(runtime_, R"( 9292def foo(obj): 9293 return -obj 9294foo(0) # Change UNARY_OP_ANAMORPHIC to UNARY_NEGATIVE_SMALLINT 9295)") 9296 .isError()); 9297 HandleScope scope(thread_); 9298 Function function(&scope, mainModuleAt(runtime_, "foo")); 9299 EXPECT_TRUE(containsBytecode(function, UNARY_NEGATIVE_SMALLINT)); 9300 Object obj(&scope, SmallInt::fromWord(-123)); 9301 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 9302 EXPECT_TRUE(isIntEqualsWord(*result, 123)); 9303} 9304 9305TEST_F(JitTest, UnaryNegativeSmallIntWithZeroReturnsZero) { 9306 if (useCppInterpreter()) { 9307 GTEST_SKIP(); 9308 } 9309 ASSERT_FALSE(runFromCStr(runtime_, R"( 9310def foo(obj): 9311 return -obj 9312foo(0) # Change UNARY_OP_ANAMORPHIC to UNARY_NEGATIVE_SMALLINT 9313)") 9314 .isError()); 9315 HandleScope scope(thread_); 9316 Function function(&scope, mainModuleAt(runtime_, "foo")); 9317 EXPECT_TRUE(containsBytecode(function, UNARY_NEGATIVE_SMALLINT)); 9318 Object obj(&scope, SmallInt::fromWord(0)); 9319 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 9320 EXPECT_TRUE(isIntEqualsWord(*result, 0)); 9321} 9322 9323TEST_F(JitTest, UnaryPositiveCallsDunderPos) { 9324 if (useCppInterpreter()) { 9325 GTEST_SKIP(); 9326 } 9327 ASSERT_FALSE(runFromCStr(runtime_, R"( 9328class C: 9329 def __pos__(self): 9330 return 5 9331def foo(obj): 9332 return +obj 9333instance = C() 9334)") 9335 .isError()); 9336 HandleScope scope(thread_); 9337 Function function(&scope, mainModuleAt(runtime_, "foo")); 9338 EXPECT_TRUE(containsBytecode(function, UNARY_POSITIVE)); 9339 Object obj(&scope, mainModuleAt(runtime_, "instance")); 9340 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 9341 EXPECT_TRUE(isIntEqualsWord(*result, 5)); 9342} 9343 9344TEST_F(JitTest, UnaryInvertCallsDunderInvert) { 9345 if (useCppInterpreter()) { 9346 GTEST_SKIP(); 9347 } 9348 ASSERT_FALSE(runFromCStr(runtime_, R"( 9349class C: 9350 def __invert__(self): 9351 return 5 9352def foo(obj): 9353 return ~obj 9354instance = C() 9355)") 9356 .isError()); 9357 HandleScope scope(thread_); 9358 Function function(&scope, mainModuleAt(runtime_, "foo")); 9359 EXPECT_TRUE(containsBytecode(function, UNARY_INVERT)); 9360 Object obj(&scope, mainModuleAt(runtime_, "instance")); 9361 Object result(&scope, compileAndCallJITFunction1(thread_, function, obj)); 9362 EXPECT_TRUE(isIntEqualsWord(*result, 5)); 9363} 9364 9365TEST_F(JitTest, BinaryMulSmallintWithSmallIntsReturnsInt) { 9366 if (useCppInterpreter()) { 9367 GTEST_SKIP(); 9368 } 9369 EXPECT_FALSE(runFromCStr(runtime_, R"( 9370def foo(left, right): 9371 return left * right 9372 9373# Rewrite BINARY_OP_ANAMORPHIC to BINARY_MUL_SMALLINT 9374foo(1, 1) 9375)") 9376 .isError()); 9377 9378 HandleScope scope(thread_); 9379 Function function(&scope, mainModuleAt(runtime_, "foo")); 9380 EXPECT_TRUE(containsBytecode(function, BINARY_MUL_SMALLINT)); 9381 Object left(&scope, SmallInt::fromWord(5)); 9382 Object right(&scope, SmallInt::fromWord(10)); 9383 Object result(&scope, 9384 compileAndCallJITFunction2(thread_, function, left, right)); 9385 EXPECT_TRUE(isIntEqualsWord(*result, 50)); 9386} 9387 9388TEST_F(JitTest, BinaryMulSmallintWithNonSmallintDeoptimizes) { 9389 if (useCppInterpreter()) { 9390 GTEST_SKIP(); 9391 } 9392 // Don't use compileAndCallJITFunction2 in this function because we want to 9393 // test deoptimizing back into the interpreter. This requires valid bytecode. 9394 EXPECT_FALSE(runFromCStr(runtime_, R"( 9395def foo(left, right): 9396 return left * right 9397 9398# Rewrite BINARY_OP_ANAMORPHIC to BINARY_MUL_SMALLINT 9399foo(1, 1) 9400)") 9401 .isError()); 9402 9403 HandleScope scope(thread_); 9404 Function function(&scope, mainModuleAt(runtime_, "foo")); 9405 EXPECT_TRUE(containsBytecode(function, BINARY_MUL_SMALLINT)); 9406 void* entry_before = function.entryAsm(); 9407 compileFunction(thread_, function); 9408 EXPECT_NE(function.entryAsm(), entry_before); 9409 Object left_str(&scope, SmallStr::fromCStr("hello")); 9410 Object right(&scope, SmallInt::fromWord(2)); 9411 Function deopt_caller(&scope, 9412 createTrampolineFunction2(thread_, left_str, right)); 9413 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 9414 EXPECT_TRUE(containsBytecode(function, BINARY_OP_MONOMORPHIC)); 9415 EXPECT_TRUE(isStrEqualsCStr(*result, "hellohello")); 9416 EXPECT_EQ(function.entryAsm(), entry_before); 9417} 9418 9419TEST_F(JitTest, BinaryMulSmallintWithOverflowDeoptimizes) { 9420 if (useCppInterpreter()) { 9421 GTEST_SKIP(); 9422 } 9423 // Don't use compileAndCallJITFunction2 in this function because we want to 9424 // test deoptimizing back into the interpreter. This requires valid bytecode. 9425 EXPECT_FALSE(runFromCStr(runtime_, R"( 9426def foo(left, right): 9427 return left * right 9428 9429# Rewrite BINARY_OP_ANAMORPHIC to BINARY_MUL_SMALLINT 9430foo(1, 1) 9431)") 9432 .isError()); 9433 9434 HandleScope scope(thread_); 9435 Function function(&scope, mainModuleAt(runtime_, "foo")); 9436 EXPECT_TRUE(containsBytecode(function, BINARY_MUL_SMALLINT)); 9437 void* entry_before = function.entryAsm(); 9438 compileFunction(thread_, function); 9439 EXPECT_NE(function.entryAsm(), entry_before); 9440 Object left(&scope, SmallInt::fromWord(SmallInt::kMaxValue)); 9441 Object right(&scope, SmallInt::fromWord(2)); 9442 Function deopt_caller(&scope, 9443 createTrampolineFunction2(thread_, left, right)); 9444 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 9445 EXPECT_TRUE(containsBytecode(function, BINARY_OP_MONOMORPHIC)); 9446 EXPECT_TRUE(isIntEqualsWord(*result, SmallInt::kMaxValue * 2)); 9447 EXPECT_EQ(function.entryAsm(), entry_before); 9448} 9449 9450TEST_F(JitTest, BinaryMulSmallintWithUnderflowDeoptimizes) { 9451 if (useCppInterpreter()) { 9452 GTEST_SKIP(); 9453 } 9454 // Don't use compileAndCallJITFunction2 in this function because we want to 9455 // test deoptimizing back into the interpreter. This requires valid bytecode. 9456 EXPECT_FALSE(runFromCStr(runtime_, R"( 9457def foo(left, right): 9458 return left * right 9459 9460# Rewrite BINARY_OP_ANAMORPHIC to BINARY_MUL_SMALLINT 9461foo(1, 1) 9462)") 9463 .isError()); 9464 9465 HandleScope scope(thread_); 9466 Function function(&scope, mainModuleAt(runtime_, "foo")); 9467 EXPECT_TRUE(containsBytecode(function, BINARY_MUL_SMALLINT)); 9468 void* entry_before = function.entryAsm(); 9469 compileFunction(thread_, function); 9470 EXPECT_NE(function.entryAsm(), entry_before); 9471 Object left(&scope, SmallInt::fromWord(SmallInt::kMinValue)); 9472 Object right(&scope, SmallInt::fromWord(2)); 9473 Function deopt_caller(&scope, 9474 createTrampolineFunction2(thread_, left, right)); 9475 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 9476 EXPECT_TRUE(containsBytecode(function, BINARY_OP_MONOMORPHIC)); 9477 EXPECT_TRUE(isIntEqualsWord(*result, SmallInt::kMinValue * 2)); 9478 EXPECT_EQ(function.entryAsm(), entry_before); 9479} 9480 9481TEST_F(JitTest, CallFunctionWithInterpretedFunctionCallsFunction) { 9482 if (useCppInterpreter()) { 9483 GTEST_SKIP(); 9484 } 9485 ASSERT_FALSE(runFromCStr(runtime_, R"( 9486def bar(a, b): 9487 return a + b 9488def foo(): 9489 return bar(3, 4) 9490# Rewrite CALL_FUNCTION_ANAMORPHIC to CALL_FUNCTION 9491foo() 9492)") 9493 .isError()); 9494 HandleScope scope(thread_); 9495 Function function(&scope, mainModuleAt(runtime_, "foo")); 9496 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 9497 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9498 EXPECT_TRUE(isIntEqualsWord(*result, 7)); 9499} 9500 9501TEST_F(JitTest, CallFunctionWithGeneratorFunctionCallsFunction) { 9502 if (useCppInterpreter()) { 9503 GTEST_SKIP(); 9504 } 9505 ASSERT_FALSE(runFromCStr(runtime_, R"( 9506def bar(a, b): 9507 yield a + b 9508def foo(): 9509 return bar(3, 4) 9510# Rewrite CALL_FUNCTION_ANAMORPHIC to CALL_FUNCTION 9511foo() 9512)") 9513 .isError()); 9514 HandleScope scope(thread_); 9515 Function function(&scope, mainModuleAt(runtime_, "foo")); 9516 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 9517 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9518 EXPECT_TRUE(result.isGenerator()); 9519} 9520 9521static ALIGN_16 RawObject addTwoNumbers(Thread*, Arguments args) { 9522 return SmallInt::fromWord(SmallInt::cast(args.get(0)).value() + 9523 SmallInt::cast(args.get(1)).value()); 9524} 9525 9526TEST_F(JitTest, CallFunctionWithBuiltinFunctionCallsFunction) { 9527 if (useCppInterpreter()) { 9528 GTEST_SKIP(); 9529 } 9530 const char* params[] = {"a", "b"}; 9531 addBuiltin("bar", addTwoNumbers, params, 0); 9532 ASSERT_FALSE(runFromCStr(runtime_, R"( 9533def foo(): 9534 return bar(3, 4) 9535# Rewrite CALL_FUNCTION_ANAMORPHIC to CALL_FUNCTION 9536foo() 9537)") 9538 .isError()); 9539 HandleScope scope(thread_); 9540 Function function(&scope, mainModuleAt(runtime_, "foo")); 9541 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 9542 Object result(&scope, compileAndCallJITFunction(thread_, function)); 9543 EXPECT_TRUE(isIntEqualsWord(*result, 7)); 9544} 9545 9546TEST_F(JitTest, CallFunctionWithCallableCallsDunderCall) { 9547 if (useCppInterpreter()) { 9548 GTEST_SKIP(); 9549 } 9550 ASSERT_FALSE(runFromCStr(runtime_, R"( 9551def function(): 9552 return 5 9553def foo(fn): 9554 return fn() 9555# Rewrite CALL_FUNCTION_ANAMORPHIC to CALL_FUNCTION 9556foo(function) 9557class C: 9558 def __call__(self): 9559 return 10 9560instance = C() 9561)") 9562 .isError()); 9563 HandleScope scope(thread_); 9564 Function function(&scope, mainModuleAt(runtime_, "foo")); 9565 EXPECT_TRUE(containsBytecode(function, CALL_FUNCTION)); 9566 Object callable(&scope, mainModuleAt(runtime_, "instance")); 9567 Object result(&scope, 9568 compileAndCallJITFunction1(thread_, function, callable)); 9569 EXPECT_TRUE(isIntEqualsWord(*result, 10)); 9570} 9571 9572TEST_F(JitTest, BinarySubscrMonomorphicCallsDunderGetitem) { 9573 if (useCppInterpreter()) { 9574 GTEST_SKIP(); 9575 } 9576 ASSERT_FALSE(runFromCStr(runtime_, R"( 9577class C: 9578 def __getitem__(self, key): 9579 return key * 2 9580 9581def foo(ls): 9582 return ls[3] 9583 9584# Rewrite BINARY_SUBSCR_ANAMORPHIC to BINARY_SUBSCR_MONOMORPHIC 9585foo(C()) 9586 9587instance = C() 9588)") 9589 .isError()); 9590 HandleScope scope(thread_); 9591 Function function(&scope, mainModuleAt(runtime_, "foo")); 9592 EXPECT_TRUE(containsBytecode(function, BINARY_SUBSCR_MONOMORPHIC)); 9593 Object callable(&scope, mainModuleAt(runtime_, "instance")); 9594 Object result(&scope, 9595 compileAndCallJITFunction1(thread_, function, callable)); 9596 EXPECT_TRUE(isIntEqualsWord(*result, 6)); 9597} 9598 9599TEST_F(JitTest, BinarySubscrMonomorphicWithNewTypeDeoptimizes) { 9600 if (useCppInterpreter()) { 9601 GTEST_SKIP(); 9602 } 9603 ASSERT_FALSE(runFromCStr(runtime_, R"( 9604class C: 9605 def __getitem__(self, key): 9606 return 7 9607 9608class D: 9609 def __getitem__(self, key): 9610 return 13 9611 9612def foo(ls): 9613 return ls[3] 9614 9615# Rewrite BINARY_SUBSCR_ANAMORPHIC to BINARY_SUBSCR_MONOMORPHIC 9616foo(C()) 9617 9618instance = D() 9619)") 9620 .isError()); 9621 HandleScope scope(thread_); 9622 Function function(&scope, mainModuleAt(runtime_, "foo")); 9623 EXPECT_TRUE(containsBytecode(function, BINARY_SUBSCR_MONOMORPHIC)); 9624 Object instance(&scope, mainModuleAt(runtime_, "instance")); 9625 void* entry_before = function.entryAsm(); 9626 compileFunction(thread_, function); 9627 EXPECT_NE(function.entryAsm(), entry_before); 9628 Function deopt_caller(&scope, createTrampolineFunction1(thread_, instance)); 9629 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 9630 EXPECT_TRUE(containsBytecode(function, BINARY_SUBSCR_POLYMORPHIC)); 9631 EXPECT_TRUE(isIntEqualsWord(*result, 13)); 9632 EXPECT_EQ(function.entryAsm(), entry_before); 9633} 9634 9635TEST_F(JitTest, StoreAttrInstanceUpdateWithInstanceStoresAttribute) { 9636 if (useCppInterpreter()) { 9637 GTEST_SKIP(); 9638 } 9639 EXPECT_FALSE(runFromCStr(runtime_, R"( 9640class C: 9641 def __init__(self, value): 9642 self.bar = value 9643 9644foo = C.__init__ 9645 9646# Rewrite STORE_ATTR_ANAMORPHIC to STORE_ATTR_INSTANCE_UPDATE 9647instance = C(10) 9648)") 9649 .isError()); 9650 HandleScope scope(thread_); 9651 Function function(&scope, mainModuleAt(runtime_, "foo")); 9652 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_INSTANCE_UPDATE)); 9653 // Don't use compileAndCallJITFunction2 in this function because the C++ 9654 // handler needs to be able to read the cache index off the bytecode. 9655 compileFunction(thread_, function); 9656 Object self(&scope, mainModuleAt(runtime_, "instance")); 9657 Object value(&scope, SmallInt::fromWord(10)); 9658 Function caller(&scope, createTrampolineFunction2(thread_, self, value)); 9659 Object result(&scope, Interpreter::call0(thread_, caller)); 9660 EXPECT_TRUE(result.isNoneType()); 9661} 9662 9663TEST_F(JitTest, StoreAttrInstanceUpdateWithNewTypeDeoptimizes) { 9664 if (useCppInterpreter()) { 9665 GTEST_SKIP(); 9666 } 9667 EXPECT_FALSE(runFromCStr(runtime_, R"( 9668class C: 9669 def __init__(self, value): 9670 self.bar = value 9671 9672foo = C.__init__ 9673 9674# Rewrite STORE_ATTR_ANAMORPHIC to STORE_ATTR_INSTANCE_UPDATE 9675instance = C(10) 9676# Change the layout of `instance' 9677instance.attr = "blah" 9678)") 9679 .isError()); 9680 9681 HandleScope scope(thread_); 9682 Function function(&scope, mainModuleAt(runtime_, "foo")); 9683 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_INSTANCE_UPDATE)); 9684 void* entry_before = function.entryAsm(); 9685 // Don't use compileAndCallJITFunction2 in this function because we want to 9686 // test deoptimizing back into the interpreter. This requires valid bytecode. 9687 compileFunction(thread_, function); 9688 EXPECT_NE(function.entryAsm(), entry_before); 9689 Object self(&scope, mainModuleAt(runtime_, "instance")); 9690 Object value(&scope, SmallInt::fromWord(10)); 9691 Function deopt_caller(&scope, 9692 createTrampolineFunction2(thread_, self, value)); 9693 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 9694 EXPECT_TRUE(result.isNoneType()); 9695 EXPECT_TRUE(containsBytecode(function, STORE_ATTR_INSTANCE)); 9696 EXPECT_EQ(function.entryAsm(), entry_before); 9697} 9698 9699TEST_F(JitTest, BinaryOpMonomorphicCallsCachedFunction) { 9700 if (useCppInterpreter()) { 9701 GTEST_SKIP(); 9702 } 9703 EXPECT_FALSE(runFromCStr(runtime_, R"( 9704class C: 9705 def __mul__(self, other): 9706 return other * 10 9707 9708def foo(left, right): 9709 return left * right 9710 9711# Rewrite BINARY_OP_ANAMORPHIC to BINARY_OP_MONOMORPHIC 9712foo(C(), 1) 9713instance = C() 9714)") 9715 .isError()); 9716 9717 HandleScope scope(thread_); 9718 Function function(&scope, mainModuleAt(runtime_, "foo")); 9719 EXPECT_TRUE(containsBytecode(function, BINARY_OP_MONOMORPHIC)); 9720 // Don't use compileAndCallJITFunction2 in this function because the C++ 9721 // handler needs to be able to read the cache index off the bytecode. 9722 compileFunction(thread_, function); 9723 Object left(&scope, mainModuleAt(runtime_, "instance")); 9724 Object right(&scope, SmallInt::fromWord(5)); 9725 Function caller(&scope, createTrampolineFunction2(thread_, left, right)); 9726 Object result(&scope, Interpreter::call0(thread_, caller)); 9727 EXPECT_TRUE(isIntEqualsWord(*result, 50)); 9728} 9729 9730TEST_F(JitTest, BinaryOpMonomorphicWithNewTypeDeoptimizes) { 9731 if (useCppInterpreter()) { 9732 GTEST_SKIP(); 9733 } 9734 // Don't use compileAndCallJITFunction2 in this function because we want to 9735 // test deoptimizing back into the interpreter. This requires valid bytecode. 9736 EXPECT_FALSE(runFromCStr(runtime_, R"( 9737class C: 9738 def __mul__(self, other): 9739 return other * 10 9740 9741class D(C): 9742 pass 9743 9744def foo(left, right): 9745 return left * right 9746 9747# Rewrite BINARY_OP_ANAMORPHIC to BINARY_MUL_SMALLINT 9748foo(C(), 1) 9749instance = D() 9750)") 9751 .isError()); 9752 9753 HandleScope scope(thread_); 9754 Function function(&scope, mainModuleAt(runtime_, "foo")); 9755 EXPECT_TRUE(containsBytecode(function, BINARY_OP_MONOMORPHIC)); 9756 void* entry_before = function.entryAsm(); 9757 compileFunction(thread_, function); 9758 EXPECT_NE(function.entryAsm(), entry_before); 9759 Object left(&scope, mainModuleAt(runtime_, "instance")); 9760 Object right(&scope, SmallInt::fromWord(2)); 9761 Function deopt_caller(&scope, 9762 createTrampolineFunction2(thread_, left, right)); 9763 Object result(&scope, Interpreter::call0(thread_, deopt_caller)); 9764 EXPECT_TRUE(containsBytecode(function, BINARY_OP_POLYMORPHIC)); 9765 EXPECT_TRUE(isIntEqualsWord(*result, 20)); 9766 EXPECT_EQ(function.entryAsm(), entry_before); 9767} 9768 9769// Benchmarks 9770class InterpreterBenchmark : public benchmark::Fixture { 9771 public: 9772 void SetUp(benchmark::State&) { 9773 runtime_ = createTestRuntime(); 9774 thread_ = Thread::current(); 9775 } 9776 9777 void TearDown(benchmark::State&) { delete runtime_; } 9778 9779 protected: 9780 Runtime* runtime_; 9781 Thread* thread_; 9782}; 9783 9784BENCHMARK_F(InterpreterBenchmark, SimpleFunction)(benchmark::State& state) { 9785 EXPECT_FALSE(runFromCStr(runtime_, R"( 9786def foo(): 9787 x = 1 9788 y = 2 9789 return x + y 9790)") 9791 .isError()); 9792 HandleScope scope(thread_); 9793 Function foo(&scope, mainModuleAt(runtime_, "foo")); 9794 for (auto _ : state) { 9795 Object result(&scope, Interpreter::call0(thread_, foo)); 9796 static_cast<void>(result); 9797 } 9798} 9799 9800} // namespace testing 9801} // namespace py