Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(500)

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 2282001: Various refactorings in interceptor calling and loading. (Closed)
Patch Set: Addressing Soeren's comments Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 optimize = callback->getter() != NULL; 454 optimize = callback->getter() != NULL;
455 } 455 }
456 } 456 }
457 457
458 if (!optimize) { 458 if (!optimize) {
459 CompileRegular(masm, receiver, holder, scratch2, interceptor_holder, 459 CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
460 miss_label); 460 miss_label);
461 return; 461 return;
462 } 462 }
463 463
464 // Note: starting a frame here makes GC aware of pointers pushed below. 464 // Save necessary data before invoking an interceptor.
465 // Requires a frame to make GC aware of pushed pointers.
465 __ EnterInternalFrame(); 466 __ EnterInternalFrame();
466 467
467 __ push(receiver); 468 if (lookup->type() == CALLBACKS && !receiver.is(holder)) {
468 __ Push(holder, name_); 469 // CALLBACKS case needs a receiver to be passed into C++ callback.
470 __ Push(receiver, holder, name_);
471 } else {
472 __ Push(holder, name_);
473 }
469 474
470 // Invoke an interceptor. Note: map checks from receiver to 475 // Invoke an interceptor. Note: map checks from receiver to
471 // interceptor's holder has been compiled before (see a caller 476 // interceptor's holder has been compiled before (see a caller
472 // of this method.) 477 // of this method.)
473 CompileCallLoadPropertyWithInterceptor(masm, 478 CompileCallLoadPropertyWithInterceptor(masm,
474 receiver, 479 receiver,
475 holder, 480 holder,
476 name_, 481 name_,
477 interceptor_holder); 482 interceptor_holder);
478 483
479 // Check if interceptor provided a value for property. If it's 484 // Check if interceptor provided a value for property. If it's
480 // the case, return immediately. 485 // the case, return immediately.
481 Label interceptor_failed; 486 Label interceptor_failed;
482 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 487 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
483 __ cmp(r0, scratch1); 488 __ cmp(r0, scratch1);
484 __ b(eq, &interceptor_failed); 489 __ b(eq, &interceptor_failed);
485 __ LeaveInternalFrame(); 490 __ LeaveInternalFrame();
486 __ Ret(); 491 __ Ret();
487 492
488 __ bind(&interceptor_failed); 493 __ bind(&interceptor_failed);
489 __ pop(name_); 494 __ pop(name_);
490 __ pop(holder); 495 __ pop(holder);
491 __ pop(receiver); 496 if (lookup->type() == CALLBACKS && !receiver.is(holder)) {
497 __ pop(receiver);
498 }
492 499
493 __ LeaveInternalFrame(); 500 __ LeaveInternalFrame();
494 501
495 if (lookup->type() == FIELD) { 502 // Check that the maps from interceptor's holder to lookup's holder
496 // We found FIELD property in prototype chain of interceptor's holder. 503 // haven't changed. And load lookup's holder into |holder| register.
497 // Check that the maps from interceptor's holder to field's holder 504 if (interceptor_holder != lookup->holder()) {
498 // haven't changed... 505 holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
499 holder = stub_compiler->CheckPrototypes(interceptor_holder, 506 lookup->holder(), scratch1,
500 holder,
501 lookup->holder(),
502 scratch1,
503 scratch2, 507 scratch2,
504 name, 508 name,
505 miss_label); 509 miss_label);
506 // ... and retrieve a field from field's holder. 510 }
511
512 if (lookup->type() == FIELD) {
513 // We found FIELD property in prototype chain of interceptor's holder.
514 // Retrieve a field from field's holder.
507 stub_compiler->GenerateFastPropertyLoad(masm, 515 stub_compiler->GenerateFastPropertyLoad(masm,
508 r0, 516 r0,
509 holder, 517 holder,
510 lookup->holder(), 518 lookup->holder(),
511 lookup->GetFieldIndex()); 519 lookup->GetFieldIndex());
512 __ Ret(); 520 __ Ret();
513 } else { 521 } else {
514 // We found CALLBACKS property in prototype chain of interceptor's 522 // We found CALLBACKS property in prototype chain of interceptor's
515 // holder. 523 // holder.
516 ASSERT(lookup->type() == CALLBACKS); 524 ASSERT(lookup->type() == CALLBACKS);
517 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); 525 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
518 ASSERT(callback != NULL); 526 ASSERT(callback != NULL);
519 ASSERT(callback->getter() != NULL); 527 ASSERT(callback->getter() != NULL);
520 528
521 // Prepare for tail call: push receiver to stack. 529 // Tail call to runtime.
522 Label cleanup; 530 // Important invariant in CALLBACKS case: the code above must be
523 __ push(receiver); 531 // structured to never clobber |receiver| register.
532 __ Move(scratch2, Handle<AccessorInfo>(callback));
533 // holder is either receiver or scratch1.
534 if (!receiver.is(holder)) {
535 ASSERT(scratch1.is(holder));
536 __ Push(receiver, holder, scratch2);
537 __ ldr(scratch1, FieldMemOperand(holder, AccessorInfo::kDataOffset));
538 __ Push(scratch1, name_);
539 } else {
540 __ push(receiver);
541 __ ldr(scratch1, FieldMemOperand(holder, AccessorInfo::kDataOffset));
542 __ Push(holder, scratch2, scratch1, name_);
543 }
524 544
525 // Check that the maps from interceptor's holder to callback's holder
526 // haven't changed.
527 holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
528 lookup->holder(), scratch1,
529 scratch2,
530 name,
531 &cleanup);
532
533 // Continue tail call preparation: push remaining parameters.
534 __ push(holder);
535 __ Move(holder, Handle<AccessorInfo>(callback));
536 __ push(holder);
537 __ ldr(scratch1, FieldMemOperand(holder, AccessorInfo::kDataOffset));
538 __ Push(scratch1, name_);
539
540 // Tail call to runtime.
541 ExternalReference ref = 545 ExternalReference ref =
542 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 546 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
543 __ TailCallExternalReference(ref, 5, 1); 547 __ TailCallExternalReference(ref, 5, 1);
544
545 // Clean up code: we pushed receiver and need to remove it.
546 __ bind(&cleanup);
547 __ pop(scratch2);
548 } 548 }
549 } 549 }
550 550
551 551
552 void CompileRegular(MacroAssembler* masm, 552 void CompileRegular(MacroAssembler* masm,
553 Register receiver, 553 Register receiver,
554 Register holder, 554 Register holder,
555 Register scratch, 555 Register scratch,
556 JSObject* interceptor_holder, 556 JSObject* interceptor_holder,
557 Label* miss_label) { 557 Label* miss_label) {
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1, 763 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1,
764 scratch1, scratch2); 764 scratch1, scratch2);
765 ReserveSpaceForFastApiCall(masm, scratch1); 765 ReserveSpaceForFastApiCall(masm, scratch1);
766 } 766 }
767 767
768 // Check that the maps from receiver to interceptor's holder 768 // Check that the maps from receiver to interceptor's holder
769 // haven't changed and thus we can invoke interceptor. 769 // haven't changed and thus we can invoke interceptor.
770 Label miss_cleanup; 770 Label miss_cleanup;
771 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 771 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
772 Register holder = 772 Register holder =
773 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 773 stub_compiler_->CheckPrototypes(object, receiver,
774 scratch1, scratch2, name, 774 interceptor_holder, scratch1,
775 depth1, miss); 775 scratch2, name, depth1, miss);
776 776
777 // Invoke an interceptor and if it provides a value, 777 // Invoke an interceptor and if it provides a value,
778 // branch to |regular_invoke|. 778 // branch to |regular_invoke|.
779 Label regular_invoke; 779 Label regular_invoke;
780 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, 780 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
781 &regular_invoke); 781 &regular_invoke);
782 782
783 // Interceptor returned nothing for this property. Try to use cached 783 // Interceptor returned nothing for this property. Try to use cached
784 // constant function. 784 // constant function.
785 785
786 // Check that the maps from interceptor's holder to constant function's 786 // Check that the maps from interceptor's holder to constant function's
787 // holder haven't changed and thus we can use cached constant function. 787 // holder haven't changed and thus we can use cached constant function.
788 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 788 if (interceptor_holder != lookup->holder()) {
789 lookup->holder(), scratch1, 789 stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
790 scratch2, name, depth2, miss); 790 lookup->holder(), scratch1,
791 scratch2, name, depth2, miss);
792 // CheckPrototypes has a side effect of fetching a 'holder'
793 // for API (object which is instanceof for the signature). It's
794 // safe to omit it here, as if present, it should be fetched
795 // by the previous CheckPrototypes.
796 ASSERT((depth2 == kInvalidProtoDepth) || (depth1 != kInvalidProtoDepth));
797 }
791 798
792 // Invoke function. 799 // Invoke function.
793 if (can_do_fast_api_call) { 800 if (can_do_fast_api_call) {
794 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 801 GenerateFastApiCall(masm, optimization, arguments_.immediate());
795 } else { 802 } else {
796 __ InvokeFunction(optimization.constant_function(), arguments_, 803 __ InvokeFunction(optimization.constant_function(), arguments_,
797 JUMP_FUNCTION); 804 JUMP_FUNCTION);
798 } 805 }
799 806
800 // Deferred code for fast API call case---clean preallocated space. 807 // Deferred code for fast API call case---clean preallocated space.
(...skipping 1363 matching lines...) Expand 10 before | Expand all | Expand 10 after
2164 // Return the generated code. 2171 // Return the generated code.
2165 return GetCode(); 2172 return GetCode();
2166 } 2173 }
2167 2174
2168 2175
2169 #undef __ 2176 #undef __
2170 2177
2171 } } // namespace v8::internal 2178 } } // namespace v8::internal
2172 2179
2173 #endif // V8_TARGET_ARCH_ARM 2180 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698