OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 // entering the runtime system. | 150 // entering the runtime system. |
151 __ bind(&miss); | 151 __ bind(&miss); |
152 } | 152 } |
153 | 153 |
154 | 154 |
155 template <typename Pushable> | 155 template <typename Pushable> |
156 static void PushInterceptorArguments(MacroAssembler* masm, | 156 static void PushInterceptorArguments(MacroAssembler* masm, |
157 Register receiver, | 157 Register receiver, |
158 Register holder, | 158 Register holder, |
159 Pushable name, | 159 Pushable name, |
160 JSObject* holder_obj, | 160 JSObject* holder_obj) { |
161 Smi* lookup_hint) { | |
162 __ push(receiver); | 161 __ push(receiver); |
163 __ push(holder); | 162 __ push(holder); |
164 __ push(name); | 163 __ push(name); |
165 // TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or | |
166 // LOOKUP_IN_PROTOTYPE, but use a special version of lookup method? | |
167 __ push(Immediate(lookup_hint)); | |
168 | |
169 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 164 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
170 __ mov(receiver, Immediate(Handle<Object>(interceptor))); | 165 __ mov(receiver, Immediate(Handle<Object>(interceptor))); |
171 __ push(receiver); | 166 __ push(receiver); |
172 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset)); | 167 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset)); |
173 } | 168 } |
174 | 169 |
175 | 170 |
176 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 171 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, |
177 int index, | 172 int index, |
178 Register prototype) { | 173 Register prototype) { |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 __ mov(dst, FieldOperand(src, offset)); | 282 __ mov(dst, FieldOperand(src, offset)); |
288 } else { | 283 } else { |
289 // Calculate the offset into the properties array. | 284 // Calculate the offset into the properties array. |
290 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 285 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
291 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 286 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
292 __ mov(dst, FieldOperand(dst, offset)); | 287 __ mov(dst, FieldOperand(dst, offset)); |
293 } | 288 } |
294 } | 289 } |
295 | 290 |
296 | 291 |
| 292 template <class Pushable> |
| 293 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
| 294 Register receiver, |
| 295 Register holder, |
| 296 Pushable name, |
| 297 JSObject* holder_obj) { |
| 298 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 299 |
| 300 ExternalReference ref = |
| 301 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); |
| 302 __ mov(eax, Immediate(5)); |
| 303 __ mov(ebx, Immediate(ref)); |
| 304 |
| 305 CEntryStub stub; |
| 306 __ CallStub(&stub); |
| 307 } |
| 308 |
| 309 |
| 310 template <class Compiler> |
| 311 static void CompileLoadInterceptor(Compiler* compiler, |
| 312 StubCompiler* stub_compiler, |
| 313 MacroAssembler* masm, |
| 314 JSObject* object, |
| 315 JSObject* holder, |
| 316 String* name, |
| 317 LookupResult* lookup, |
| 318 Register receiver, |
| 319 Register scratch1, |
| 320 Register scratch2, |
| 321 Label* miss) { |
| 322 ASSERT(holder->HasNamedInterceptor()); |
| 323 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 324 |
| 325 // Check that the receiver isn't a smi. |
| 326 __ test(receiver, Immediate(kSmiTagMask)); |
| 327 __ j(zero, miss, not_taken); |
| 328 |
| 329 // Check that the maps haven't changed. |
| 330 Register reg = |
| 331 stub_compiler->CheckPrototypes(object, receiver, holder, |
| 332 scratch1, scratch2, name, miss); |
| 333 |
| 334 if (lookup->IsValid() && lookup->IsCacheable()) { |
| 335 compiler->CompileCacheable(masm, |
| 336 stub_compiler, |
| 337 receiver, |
| 338 reg, |
| 339 scratch1, |
| 340 scratch2, |
| 341 holder, |
| 342 lookup, |
| 343 name, |
| 344 miss); |
| 345 } else { |
| 346 compiler->CompileRegular(masm, |
| 347 receiver, |
| 348 reg, |
| 349 scratch2, |
| 350 holder, |
| 351 miss); |
| 352 } |
| 353 } |
| 354 |
| 355 |
| 356 static void LookupPostInterceptor(JSObject* holder, |
| 357 String* name, |
| 358 LookupResult* lookup) { |
| 359 holder->LocalLookupRealNamedProperty(name, lookup); |
| 360 if (lookup->IsNotFound()) { |
| 361 Object* proto = holder->GetPrototype(); |
| 362 if (proto != Heap::null_value()) { |
| 363 proto->Lookup(name, lookup); |
| 364 } |
| 365 } |
| 366 } |
| 367 |
| 368 |
| 369 class LoadInterceptorCompiler BASE_EMBEDDED { |
| 370 public: |
| 371 explicit LoadInterceptorCompiler(Register name) : name_(name) {} |
| 372 |
| 373 void CompileCacheable(MacroAssembler* masm, |
| 374 StubCompiler* stub_compiler, |
| 375 Register receiver, |
| 376 Register holder, |
| 377 Register scratch1, |
| 378 Register scratch2, |
| 379 JSObject* holder_obj, |
| 380 LookupResult* lookup, |
| 381 String* name, |
| 382 Label* miss_label) { |
| 383 AccessorInfo* callback = 0; |
| 384 bool optimize = false; |
| 385 // So far the most popular follow ups for interceptor loads are FIELD |
| 386 // and CALLBACKS, so inline only them, other cases may be added |
| 387 // later. |
| 388 if (lookup->type() == FIELD) { |
| 389 optimize = true; |
| 390 } else if (lookup->type() == CALLBACKS) { |
| 391 Object* callback_object = lookup->GetCallbackObject(); |
| 392 if (callback_object->IsAccessorInfo()) { |
| 393 callback = AccessorInfo::cast(callback_object); |
| 394 optimize = callback->getter() != NULL; |
| 395 } |
| 396 } |
| 397 |
| 398 if (!optimize) { |
| 399 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); |
| 400 return; |
| 401 } |
| 402 |
| 403 // Note: starting a frame here makes GC aware of pointers pushed below. |
| 404 __ EnterInternalFrame(); |
| 405 |
| 406 if (lookup->type() == CALLBACKS) { |
| 407 __ push(receiver); |
| 408 } |
| 409 __ push(holder); |
| 410 __ push(name_); |
| 411 |
| 412 CompileCallLoadPropertyWithInterceptor(masm, |
| 413 receiver, |
| 414 holder, |
| 415 name_, |
| 416 holder_obj); |
| 417 |
| 418 Label interceptor_failed; |
| 419 __ cmp(eax, Factory::no_interceptor_result_sentinel()); |
| 420 __ j(equal, &interceptor_failed); |
| 421 __ LeaveInternalFrame(); |
| 422 __ ret(0); |
| 423 |
| 424 __ bind(&interceptor_failed); |
| 425 __ pop(name_); |
| 426 __ pop(holder); |
| 427 if (lookup->type() == CALLBACKS) { |
| 428 __ pop(receiver); |
| 429 } |
| 430 |
| 431 __ LeaveInternalFrame(); |
| 432 |
| 433 if (lookup->type() == FIELD) { |
| 434 holder = stub_compiler->CheckPrototypes(holder_obj, holder, |
| 435 lookup->holder(), scratch1, |
| 436 scratch2, |
| 437 name, |
| 438 miss_label); |
| 439 stub_compiler->GenerateFastPropertyLoad(masm, eax, |
| 440 holder, lookup->holder(), |
| 441 lookup->GetFieldIndex()); |
| 442 __ ret(0); |
| 443 } else { |
| 444 ASSERT(lookup->type() == CALLBACKS); |
| 445 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); |
| 446 ASSERT(callback != NULL); |
| 447 ASSERT(callback->getter() != NULL); |
| 448 |
| 449 Label cleanup; |
| 450 __ pop(scratch2); |
| 451 __ push(receiver); |
| 452 __ push(scratch2); |
| 453 |
| 454 holder = stub_compiler->CheckPrototypes(holder_obj, holder, |
| 455 lookup->holder(), scratch1, |
| 456 scratch2, |
| 457 name, |
| 458 &cleanup); |
| 459 |
| 460 __ pop(scratch2); // save old return address |
| 461 __ push(holder); |
| 462 __ mov(holder, Immediate(Handle<AccessorInfo>(callback))); |
| 463 __ push(holder); |
| 464 __ push(FieldOperand(holder, AccessorInfo::kDataOffset)); |
| 465 __ push(name_); |
| 466 __ push(scratch2); // restore old return address |
| 467 |
| 468 ExternalReference ref = |
| 469 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); |
| 470 __ TailCallRuntime(ref, 5); |
| 471 |
| 472 __ bind(&cleanup); |
| 473 __ pop(scratch1); |
| 474 __ pop(scratch2); |
| 475 __ push(scratch1); |
| 476 } |
| 477 } |
| 478 |
| 479 |
| 480 void CompileRegular(MacroAssembler* masm, |
| 481 Register receiver, |
| 482 Register holder, |
| 483 Register scratch, |
| 484 JSObject* holder_obj, |
| 485 Label* miss_label) { |
| 486 __ pop(scratch); // save old return address |
| 487 PushInterceptorArguments(masm, receiver, holder, name_, holder_obj); |
| 488 __ push(scratch); // restore old return address |
| 489 |
| 490 ExternalReference ref = ExternalReference( |
| 491 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); |
| 492 __ TailCallRuntime(ref, 5); |
| 493 } |
| 494 |
| 495 private: |
| 496 Register name_; |
| 497 }; |
| 498 |
| 499 |
| 500 class CallInterceptorCompiler BASE_EMBEDDED { |
| 501 public: |
| 502 explicit CallInterceptorCompiler(const ParameterCount& arguments) |
| 503 : arguments_(arguments), argc_(arguments.immediate()) {} |
| 504 |
| 505 void CompileCacheable(MacroAssembler* masm, |
| 506 StubCompiler* stub_compiler, |
| 507 Register receiver, |
| 508 Register holder, |
| 509 Register scratch1, |
| 510 Register scratch2, |
| 511 JSObject* holder_obj, |
| 512 LookupResult* lookup, |
| 513 String* name, |
| 514 Label* miss_label) { |
| 515 JSFunction* function = 0; |
| 516 bool optimize = false; |
| 517 // So far the most popular case for failed interceptor is |
| 518 // CONSTANT_FUNCTION sitting below. |
| 519 if (lookup->type() == CONSTANT_FUNCTION) { |
| 520 function = lookup->GetConstantFunction(); |
| 521 // JSArray holder is a special case for call constant function |
| 522 // (see the corresponding code). |
| 523 if (function->is_compiled() && !holder_obj->IsJSArray()) { |
| 524 optimize = true; |
| 525 } |
| 526 } |
| 527 |
| 528 if (!optimize) { |
| 529 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); |
| 530 return; |
| 531 } |
| 532 |
| 533 __ EnterInternalFrame(); |
| 534 __ push(holder); // save the holder |
| 535 |
| 536 CompileCallLoadPropertyWithInterceptor( |
| 537 masm, |
| 538 receiver, |
| 539 holder, |
| 540 // Under EnterInternalFrame this refers to name. |
| 541 Operand(ebp, (argc_ + 3) * kPointerSize), |
| 542 holder_obj); |
| 543 |
| 544 __ pop(receiver); // restore holder |
| 545 __ LeaveInternalFrame(); |
| 546 |
| 547 __ cmp(eax, Factory::no_interceptor_result_sentinel()); |
| 548 Label invoke; |
| 549 __ j(not_equal, &invoke); |
| 550 |
| 551 stub_compiler->CheckPrototypes(holder_obj, receiver, |
| 552 lookup->holder(), scratch1, |
| 553 scratch2, |
| 554 name, |
| 555 miss_label); |
| 556 if (lookup->holder()->IsGlobalObject()) { |
| 557 __ mov(edx, Operand(esp, (argc_ + 1) * kPointerSize)); |
| 558 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 559 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edx); |
| 560 } |
| 561 |
| 562 ASSERT(function->is_compiled()); |
| 563 // Get the function and setup the context. |
| 564 __ mov(edi, Immediate(Handle<JSFunction>(function))); |
| 565 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 566 |
| 567 // Jump to the cached code (tail call). |
| 568 ASSERT(function->is_compiled()); |
| 569 Handle<Code> code(function->code()); |
| 570 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 571 __ InvokeCode(code, expected, arguments_, |
| 572 RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
| 573 |
| 574 __ bind(&invoke); |
| 575 } |
| 576 |
| 577 void CompileRegular(MacroAssembler* masm, |
| 578 Register receiver, |
| 579 Register holder, |
| 580 Register scratch, |
| 581 JSObject* holder_obj, |
| 582 Label* miss_label) { |
| 583 __ EnterInternalFrame(); |
| 584 |
| 585 PushInterceptorArguments(masm, |
| 586 receiver, |
| 587 holder, |
| 588 Operand(ebp, (argc_ + 3) * kPointerSize), |
| 589 holder_obj); |
| 590 |
| 591 ExternalReference ref = ExternalReference( |
| 592 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); |
| 593 __ mov(eax, Immediate(5)); |
| 594 __ mov(ebx, Immediate(ref)); |
| 595 |
| 596 CEntryStub stub; |
| 597 __ CallStub(&stub); |
| 598 |
| 599 __ LeaveInternalFrame(); |
| 600 } |
| 601 |
| 602 private: |
| 603 const ParameterCount& arguments_; |
| 604 int argc_; |
| 605 }; |
| 606 |
| 607 |
297 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 608 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
298 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 609 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
299 Code* code = NULL; | 610 Code* code = NULL; |
300 if (kind == Code::LOAD_IC) { | 611 if (kind == Code::LOAD_IC) { |
301 code = Builtins::builtin(Builtins::LoadIC_Miss); | 612 code = Builtins::builtin(Builtins::LoadIC_Miss); |
302 } else { | 613 } else { |
303 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); | 614 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); |
304 } | 615 } |
305 | 616 |
306 Handle<Code> ic(code); | 617 Handle<Code> ic(code); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 scratch1, scratch2, name, miss); | 811 scratch1, scratch2, name, miss); |
501 | 812 |
502 // Return the constant value. | 813 // Return the constant value. |
503 __ mov(eax, Handle<Object>(value)); | 814 __ mov(eax, Handle<Object>(value)); |
504 __ ret(0); | 815 __ ret(0); |
505 } | 816 } |
506 | 817 |
507 | 818 |
508 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 819 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
509 JSObject* holder, | 820 JSObject* holder, |
510 Smi* lookup_hint, | 821 LookupResult* lookup, |
511 Register receiver, | 822 Register receiver, |
512 Register name_reg, | 823 Register name_reg, |
513 Register scratch1, | 824 Register scratch1, |
514 Register scratch2, | 825 Register scratch2, |
515 String* name, | 826 String* name, |
516 Label* miss) { | 827 Label* miss) { |
517 // Check that the receiver isn't a smi. | 828 LoadInterceptorCompiler compiler(name_reg); |
518 __ test(receiver, Immediate(kSmiTagMask)); | 829 CompileLoadInterceptor(&compiler, |
519 __ j(zero, miss, not_taken); | 830 this, |
520 | 831 masm(), |
521 // Check that the maps haven't changed. | 832 object, |
522 Register reg = | 833 holder, |
523 CheckPrototypes(object, receiver, holder, | 834 name, |
524 scratch1, scratch2, name, miss); | 835 lookup, |
525 | 836 receiver, |
526 // Push the arguments on the JS stack of the caller. | 837 scratch1, |
527 __ pop(scratch2); // remove return address | 838 scratch2, |
528 PushInterceptorArguments(masm(), | 839 miss); |
529 receiver, | |
530 reg, | |
531 name_reg, | |
532 holder, | |
533 lookup_hint); | |
534 __ push(scratch2); // restore return address | |
535 | |
536 // Do tail-call to the runtime system. | |
537 ExternalReference load_ic_property = | |
538 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty)); | |
539 __ TailCallRuntime(load_ic_property, 6); | |
540 } | 840 } |
541 | 841 |
542 | 842 |
543 // TODO(1241006): Avoid having lazy compile stubs specialized by the | 843 // TODO(1241006): Avoid having lazy compile stubs specialized by the |
544 // number of arguments. It is not needed anymore. | 844 // number of arguments. It is not needed anymore. |
545 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) { | 845 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) { |
546 // Enter an internal frame. | 846 // Enter an internal frame. |
547 __ EnterInternalFrame(); | 847 __ EnterInternalFrame(); |
548 | 848 |
549 // Push a copy of the function onto the stack. | 849 // Push a copy of the function onto the stack. |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 Object* CallStubCompiler::CompileCallInterceptor(Object* object, | 1042 Object* CallStubCompiler::CompileCallInterceptor(Object* object, |
743 JSObject* holder, | 1043 JSObject* holder, |
744 String* name) { | 1044 String* name) { |
745 // ----------- S t a t e ------------- | 1045 // ----------- S t a t e ------------- |
746 // ----------------------------------- | 1046 // ----------------------------------- |
747 Label miss; | 1047 Label miss; |
748 | 1048 |
749 // Get the number of arguments. | 1049 // Get the number of arguments. |
750 const int argc = arguments().immediate(); | 1050 const int argc = arguments().immediate(); |
751 | 1051 |
| 1052 LookupResult lookup; |
| 1053 LookupPostInterceptor(holder, name, &lookup); |
| 1054 |
752 // Get the receiver from the stack. | 1055 // Get the receiver from the stack. |
753 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1056 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
754 | 1057 |
755 // Check that the receiver isn't a smi. | 1058 CallInterceptorCompiler compiler(arguments()); |
756 __ test(edx, Immediate(kSmiTagMask)); | 1059 CompileLoadInterceptor(&compiler, |
757 __ j(zero, &miss, not_taken); | 1060 this, |
| 1061 masm(), |
| 1062 JSObject::cast(object), |
| 1063 holder, |
| 1064 name, |
| 1065 &lookup, |
| 1066 edx, |
| 1067 ebx, |
| 1068 ecx, |
| 1069 &miss); |
758 | 1070 |
759 // Check that maps have not changed and compute the holder register. | 1071 // Restore receiver. |
760 Register reg = | 1072 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
761 CheckPrototypes(JSObject::cast(object), edx, holder, | |
762 ebx, ecx, name, &miss); | |
763 | |
764 // Enter an internal frame. | |
765 __ EnterInternalFrame(); | |
766 | |
767 // Push arguments on the expression stack. | |
768 PushInterceptorArguments(masm(), | |
769 edx, | |
770 reg, | |
771 Operand(ebp, (argc + 3) * kPointerSize), | |
772 holder, | |
773 holder->InterceptorPropertyLookupHint(name)); | |
774 | |
775 // Perform call. | |
776 ExternalReference load_interceptor = | |
777 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty)); | |
778 __ mov(eax, Immediate(6)); | |
779 __ mov(ebx, Immediate(load_interceptor)); | |
780 | |
781 CEntryStub stub; | |
782 __ CallStub(&stub); | |
783 | |
784 // Move result to edi and restore receiver. | |
785 __ mov(edi, eax); | |
786 __ mov(edx, Operand(ebp, (argc + 2) * kPointerSize)); // receiver | |
787 | |
788 // Exit frame. | |
789 __ LeaveInternalFrame(); | |
790 | 1073 |
791 // Check that the function really is a function. | 1074 // Check that the function really is a function. |
792 __ test(edi, Immediate(kSmiTagMask)); | 1075 __ test(eax, Immediate(kSmiTagMask)); |
793 __ j(zero, &miss, not_taken); | 1076 __ j(zero, &miss, not_taken); |
794 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1077 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
795 __ j(not_equal, &miss, not_taken); | 1078 __ j(not_equal, &miss, not_taken); |
796 | 1079 |
797 // Patch the receiver on the stack with the global proxy if | 1080 // Patch the receiver on the stack with the global proxy if |
798 // necessary. | 1081 // necessary. |
799 if (object->IsGlobalObject()) { | 1082 if (object->IsGlobalObject()) { |
800 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1083 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
801 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1084 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
802 } | 1085 } |
803 | 1086 |
804 // Invoke the function. | 1087 // Invoke the function. |
| 1088 __ mov(edi, eax); |
805 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); | 1089 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); |
806 | 1090 |
807 // Handle load cache miss. | 1091 // Handle load cache miss. |
808 __ bind(&miss); | 1092 __ bind(&miss); |
809 Handle<Code> ic = ComputeCallMiss(argc); | 1093 Handle<Code> ic = ComputeCallMiss(argc); |
810 __ jmp(ic, RelocInfo::CODE_TARGET); | 1094 __ jmp(ic, RelocInfo::CODE_TARGET); |
811 | 1095 |
812 // Return the generated code. | 1096 // Return the generated code. |
813 return GetCode(INTERCEPTOR, name); | 1097 return GetCode(INTERCEPTOR, name); |
814 } | 1098 } |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1166 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 1450 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
1167 JSObject* holder, | 1451 JSObject* holder, |
1168 String* name) { | 1452 String* name) { |
1169 // ----------- S t a t e ------------- | 1453 // ----------- S t a t e ------------- |
1170 // -- ecx : name | 1454 // -- ecx : name |
1171 // -- esp[0] : return address | 1455 // -- esp[0] : return address |
1172 // -- esp[4] : receiver | 1456 // -- esp[4] : receiver |
1173 // ----------------------------------- | 1457 // ----------------------------------- |
1174 Label miss; | 1458 Label miss; |
1175 | 1459 |
| 1460 LookupResult lookup; |
| 1461 LookupPostInterceptor(holder, name, &lookup); |
| 1462 |
1176 __ mov(eax, Operand(esp, kPointerSize)); | 1463 __ mov(eax, Operand(esp, kPointerSize)); |
1177 // TODO(368): Compile in the whole chain: all the interceptors in | 1464 // TODO(368): Compile in the whole chain: all the interceptors in |
1178 // prototypes and ultimate answer. | 1465 // prototypes and ultimate answer. |
1179 GenerateLoadInterceptor(receiver, | 1466 GenerateLoadInterceptor(receiver, |
1180 holder, | 1467 holder, |
1181 holder->InterceptorPropertyLookupHint(name), | 1468 &lookup, |
1182 eax, | 1469 eax, |
1183 ecx, | 1470 ecx, |
1184 edx, | 1471 edx, |
1185 ebx, | 1472 ebx, |
1186 name, | 1473 name, |
1187 &miss); | 1474 &miss); |
1188 | 1475 |
1189 __ bind(&miss); | 1476 __ bind(&miss); |
1190 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1477 GenerateLoadMiss(masm(), Code::LOAD_IC); |
1191 | 1478 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1346 Label miss; | 1633 Label miss; |
1347 | 1634 |
1348 __ mov(eax, Operand(esp, kPointerSize)); | 1635 __ mov(eax, Operand(esp, kPointerSize)); |
1349 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | 1636 __ mov(ecx, Operand(esp, 2 * kPointerSize)); |
1350 __ IncrementCounter(&Counters::keyed_load_interceptor, 1); | 1637 __ IncrementCounter(&Counters::keyed_load_interceptor, 1); |
1351 | 1638 |
1352 // Check that the name has not changed. | 1639 // Check that the name has not changed. |
1353 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 1640 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
1354 __ j(not_equal, &miss, not_taken); | 1641 __ j(not_equal, &miss, not_taken); |
1355 | 1642 |
| 1643 LookupResult lookup; |
| 1644 LookupPostInterceptor(holder, name, &lookup); |
1356 GenerateLoadInterceptor(receiver, | 1645 GenerateLoadInterceptor(receiver, |
1357 holder, | 1646 holder, |
1358 Smi::FromInt(JSObject::kLookupInHolder), | 1647 &lookup, |
1359 ecx, | 1648 ecx, |
1360 eax, | 1649 eax, |
1361 edx, | 1650 edx, |
1362 ebx, | 1651 ebx, |
1363 name, | 1652 name, |
1364 &miss); | 1653 &miss); |
1365 __ bind(&miss); | 1654 __ bind(&miss); |
1366 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); | 1655 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); |
1367 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1656 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
1368 | 1657 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1447 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1736 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
1448 | 1737 |
1449 // Return the generated code. | 1738 // Return the generated code. |
1450 return GetCode(CALLBACKS, name); | 1739 return GetCode(CALLBACKS, name); |
1451 } | 1740 } |
1452 | 1741 |
1453 | 1742 |
1454 #undef __ | 1743 #undef __ |
1455 | 1744 |
1456 } } // namespace v8::internal | 1745 } } // namespace v8::internal |
OLD | NEW |