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

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

Issue 2124021: Comment the code for loading and calling with interceptor. (Closed)
Patch Set: Minor corrections Created 10 years, 7 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
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 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 class LoadInterceptorCompiler BASE_EMBEDDED { 349 class LoadInterceptorCompiler BASE_EMBEDDED {
350 public: 350 public:
351 explicit LoadInterceptorCompiler(Register name) : name_(name) {} 351 explicit LoadInterceptorCompiler(Register name) : name_(name) {}
352 352
353 void CompileCacheable(MacroAssembler* masm, 353 void CompileCacheable(MacroAssembler* masm,
354 StubCompiler* stub_compiler, 354 StubCompiler* stub_compiler,
355 Register receiver, 355 Register receiver,
356 Register holder, 356 Register holder,
357 Register scratch1, 357 Register scratch1,
358 Register scratch2, 358 Register scratch2,
359 JSObject* holder_obj, 359 JSObject* interceptor_holder,
360 LookupResult* lookup, 360 LookupResult* lookup,
361 String* name, 361 String* name,
362 Label* miss_label) { 362 Label* miss_label) {
363 AccessorInfo* callback = NULL; 363 AccessorInfo* callback = NULL;
364 bool optimize = false; 364 bool optimize = false;
365 // So far the most popular follow ups for interceptor loads are FIELD 365 // So far the most popular follow ups for interceptor loads are FIELD
366 // and CALLBACKS, so inline only them, other cases may be added 366 // and CALLBACKS, so inline only them, other cases may be added
367 // later. 367 // later.
368 if (lookup->type() == FIELD) { 368 if (lookup->type() == FIELD) {
369 optimize = true; 369 optimize = true;
370 } else if (lookup->type() == CALLBACKS) { 370 } else if (lookup->type() == CALLBACKS) {
371 Object* callback_object = lookup->GetCallbackObject(); 371 Object* callback_object = lookup->GetCallbackObject();
372 if (callback_object->IsAccessorInfo()) { 372 if (callback_object->IsAccessorInfo()) {
373 callback = AccessorInfo::cast(callback_object); 373 callback = AccessorInfo::cast(callback_object);
374 optimize = callback->getter() != NULL; 374 optimize = callback->getter() != NULL;
375 } 375 }
376 } 376 }
377 377
378 if (!optimize) { 378 if (!optimize) {
379 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); 379 CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
380 miss_label);
380 return; 381 return;
381 } 382 }
382 383
383 // Note: starting a frame here makes GC aware of pointers pushed below. 384 // Note: starting a frame here makes GC aware of pointers pushed below.
384 __ EnterInternalFrame(); 385 __ EnterInternalFrame();
385 386
386 if (lookup->type() == CALLBACKS) { 387 if (lookup->type() == CALLBACKS) {
387 __ push(receiver); 388 __ push(receiver);
388 } 389 }
389 __ push(holder); 390 __ push(holder);
390 __ push(name_); 391 __ push(name_);
391 392
393 // Invoke an interceptor. Note: map checks from receiver to
394 // interceptor's holder has been compiled before (see a caller
395 // of this method.)
392 CompileCallLoadPropertyWithInterceptor(masm, 396 CompileCallLoadPropertyWithInterceptor(masm,
393 receiver, 397 receiver,
394 holder, 398 holder,
395 name_, 399 name_,
396 holder_obj); 400 interceptor_holder);
397 401
402 // Check if interceptor provided a value for property. If it's
403 // the case, return immediately.
398 Label interceptor_failed; 404 Label interceptor_failed;
399 __ cmp(eax, Factory::no_interceptor_result_sentinel()); 405 __ cmp(eax, Factory::no_interceptor_result_sentinel());
400 __ j(equal, &interceptor_failed); 406 __ j(equal, &interceptor_failed);
401 __ LeaveInternalFrame(); 407 __ LeaveInternalFrame();
402 __ ret(0); 408 __ ret(0);
403 409
404 __ bind(&interceptor_failed); 410 __ bind(&interceptor_failed);
405 __ pop(name_); 411 __ pop(name_);
406 __ pop(holder); 412 __ pop(holder);
407 if (lookup->type() == CALLBACKS) { 413 if (lookup->type() == CALLBACKS) {
408 __ pop(receiver); 414 __ pop(receiver);
409 } 415 }
410 416
411 __ LeaveInternalFrame(); 417 __ LeaveInternalFrame();
412 418
413 if (lookup->type() == FIELD) { 419 if (lookup->type() == FIELD) {
414 holder = stub_compiler->CheckPrototypes(holder_obj, holder, 420 // We found FIELD property in prototype chain of interceptor's holder.
421 // Check that the maps from interceptor's holder to field's holder
422 // haven't changed...
423 holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
415 lookup->holder(), scratch1, 424 lookup->holder(), scratch1,
416 scratch2, 425 scratch2,
417 name, 426 name,
418 miss_label); 427 miss_label);
428 // ... and retrieve a field from field's holder.
419 stub_compiler->GenerateFastPropertyLoad(masm, eax, 429 stub_compiler->GenerateFastPropertyLoad(masm, eax,
420 holder, lookup->holder(), 430 holder, lookup->holder(),
421 lookup->GetFieldIndex()); 431 lookup->GetFieldIndex());
422 __ ret(0); 432 __ ret(0);
423 } else { 433 } else {
434 // We found CALLBACKS property in prototype chain of interceptor's
435 // holder.
424 ASSERT(lookup->type() == CALLBACKS); 436 ASSERT(lookup->type() == CALLBACKS);
425 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); 437 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
426 ASSERT(callback != NULL); 438 ASSERT(callback != NULL);
427 ASSERT(callback->getter() != NULL); 439 ASSERT(callback->getter() != NULL);
428 440
441 // Prepare for tail call: push receiver to stack after return address.
429 Label cleanup; 442 Label cleanup;
430 __ pop(scratch2); 443 __ pop(scratch2); // return address
431 __ push(receiver); 444 __ push(receiver);
432 __ push(scratch2); 445 __ push(scratch2);
433 446
434 holder = stub_compiler->CheckPrototypes(holder_obj, holder, 447 // Check that the maps from interceptor's holder to callback's holder
448 // haven't changed.
449 holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
435 lookup->holder(), scratch1, 450 lookup->holder(), scratch1,
436 scratch2, 451 scratch2,
437 name, 452 name,
438 &cleanup); 453 &cleanup);
439 454
440 __ pop(scratch2); // save old return address 455 // Continue tail call preparation: push remaining parameters after
456 // return address.
457 __ pop(scratch2); // return address
441 __ push(holder); 458 __ push(holder);
442 __ mov(holder, Immediate(Handle<AccessorInfo>(callback))); 459 __ mov(holder, Immediate(Handle<AccessorInfo>(callback)));
443 __ push(holder); 460 __ push(holder);
444 __ push(FieldOperand(holder, AccessorInfo::kDataOffset)); 461 __ push(FieldOperand(holder, AccessorInfo::kDataOffset));
445 __ push(name_); 462 __ push(name_);
446 __ push(scratch2); // restore old return address 463 __ push(scratch2); // restore return address
447 464
465 // Tail call to runtime.
448 ExternalReference ref = 466 ExternalReference ref =
449 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 467 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
450 __ TailCallExternalReference(ref, 5, 1); 468 __ TailCallExternalReference(ref, 5, 1);
451 469
470 // Clean up code: we pushed receiver after return address and
471 // need to remove it from there.
452 __ bind(&cleanup); 472 __ bind(&cleanup);
453 __ pop(scratch1); 473 __ pop(scratch1); // return address.
454 __ pop(scratch2); 474 __ pop(scratch2); // receiver.
455 __ push(scratch1); 475 __ push(scratch1);
456 } 476 }
457 } 477 }
458 478
459 479
460 void CompileRegular(MacroAssembler* masm, 480 void CompileRegular(MacroAssembler* masm,
461 Register receiver, 481 Register receiver,
462 Register holder, 482 Register holder,
463 Register scratch, 483 Register scratch,
464 JSObject* holder_obj, 484 JSObject* interceptor_holder,
465 Label* miss_label) { 485 Label* miss_label) {
466 __ pop(scratch); // save old return address 486 __ pop(scratch); // save old return address
467 PushInterceptorArguments(masm, receiver, holder, name_, holder_obj); 487 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
468 __ push(scratch); // restore old return address 488 __ push(scratch); // restore old return address
469 489
470 ExternalReference ref = ExternalReference( 490 ExternalReference ref = ExternalReference(
471 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 491 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
472 __ TailCallExternalReference(ref, 5, 1); 492 __ TailCallExternalReference(ref, 5, 1);
473 } 493 }
474 494
475 private: 495 private:
476 Register name_; 496 Register name_;
477 }; 497 };
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 miss); 639 miss);
620 } 640 }
621 } 641 }
622 642
623 private: 643 private:
624 void CompileCacheable(MacroAssembler* masm, 644 void CompileCacheable(MacroAssembler* masm,
625 JSObject* object, 645 JSObject* object,
626 Register receiver, 646 Register receiver,
627 Register scratch1, 647 Register scratch1,
628 Register scratch2, 648 Register scratch2,
629 JSObject* holder_obj, 649 JSObject* interceptor_holder,
630 LookupResult* lookup, 650 LookupResult* lookup,
631 String* name, 651 String* name,
632 const CallOptimization& optimization, 652 const CallOptimization& optimization,
633 Label* miss_label) { 653 Label* miss_label) {
634 ASSERT(optimization.is_constant_call()); 654 ASSERT(optimization.is_constant_call());
635 ASSERT(!lookup->holder()->IsGlobalObject()); 655 ASSERT(!lookup->holder()->IsGlobalObject());
636 656
637 int depth1 = kInvalidProtoDepth; 657 int depth1 = kInvalidProtoDepth;
638 int depth2 = kInvalidProtoDepth; 658 int depth2 = kInvalidProtoDepth;
639 bool can_do_fast_api_call = false; 659 bool can_do_fast_api_call = false;
640 if (optimization.is_simple_api_call() && 660 if (optimization.is_simple_api_call() &&
641 !lookup->holder()->IsGlobalObject()) { 661 !lookup->holder()->IsGlobalObject()) {
642 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj); 662 depth1 =
663 optimization.GetPrototypeDepthOfExpectedType(object,
664 interceptor_holder);
643 if (depth1 == kInvalidProtoDepth) { 665 if (depth1 == kInvalidProtoDepth) {
644 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj, 666 depth2 =
645 lookup->holder()); 667 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
668 lookup->holder());
646 } 669 }
647 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || 670 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
648 (depth2 != kInvalidProtoDepth); 671 (depth2 != kInvalidProtoDepth);
649 } 672 }
650 673
651 __ IncrementCounter(&Counters::call_const_interceptor, 1); 674 __ IncrementCounter(&Counters::call_const_interceptor, 1);
652 675
653 if (can_do_fast_api_call) { 676 if (can_do_fast_api_call) {
654 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1); 677 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1);
655 ReserveSpaceForFastApiCall(masm, scratch1); 678 ReserveSpaceForFastApiCall(masm, scratch1);
656 } 679 }
657 680
681 // Check that the maps from receiver to interceptor's holder
682 // haven't changed and thus we can invoke interceptor.
658 Label miss_cleanup; 683 Label miss_cleanup;
659 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 684 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
660 Register holder = 685 Register holder =
661 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, 686 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
662 scratch1, scratch2, name, 687 scratch1, scratch2, name,
663 depth1, miss); 688 depth1, miss);
664 689
690 // Invoke an interceptor and if it provides a value,
691 // branch to |regular_invoke|.
665 Label regular_invoke; 692 Label regular_invoke;
666 LoadWithInterceptor(masm, receiver, holder, holder_obj, &regular_invoke); 693 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
694 &regular_invoke);
667 695
668 // Generate code for the failed interceptor case. 696 // Interceptor returned nothing for this property. Try to use cached
697 // constant function.
669 698
670 // Check the lookup is still valid. 699 // Check that the maps from interceptor's holder to constant function's
671 stub_compiler_->CheckPrototypes(holder_obj, receiver, 700 // holder haven't changed and thus we can use cached constant function.
701 stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
672 lookup->holder(), 702 lookup->holder(),
673 scratch1, scratch2, name, 703 scratch1, scratch2, name,
674 depth2, miss); 704 depth2, miss);
675 705
706 // Invoke function.
676 if (can_do_fast_api_call) { 707 if (can_do_fast_api_call) {
677 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 708 GenerateFastApiCall(masm, optimization, arguments_.immediate());
678 } else { 709 } else {
679 __ InvokeFunction(optimization.constant_function(), arguments_, 710 __ InvokeFunction(optimization.constant_function(), arguments_,
680 JUMP_FUNCTION); 711 JUMP_FUNCTION);
681 } 712 }
682 713
714 // Deferred code for fast API call case---clean preallocated space.
683 if (can_do_fast_api_call) { 715 if (can_do_fast_api_call) {
684 __ bind(&miss_cleanup); 716 __ bind(&miss_cleanup);
685 FreeSpaceForFastApiCall(masm, scratch1); 717 FreeSpaceForFastApiCall(masm, scratch1);
686 __ jmp(miss_label); 718 __ jmp(miss_label);
687 } 719 }
688 720
721 // Invoke a regular function.
689 __ bind(&regular_invoke); 722 __ bind(&regular_invoke);
690 if (can_do_fast_api_call) { 723 if (can_do_fast_api_call) {
691 FreeSpaceForFastApiCall(masm, scratch1); 724 FreeSpaceForFastApiCall(masm, scratch1);
692 } 725 }
693 } 726 }
694 727
695 void CompileRegular(MacroAssembler* masm, 728 void CompileRegular(MacroAssembler* masm,
696 JSObject* object, 729 JSObject* object,
697 Register receiver, 730 Register receiver,
698 Register scratch1, 731 Register scratch1,
699 Register scratch2, 732 Register scratch2,
700 String* name, 733 String* name,
701 JSObject* holder_obj, 734 JSObject* interceptor_holder,
702 Label* miss_label) { 735 Label* miss_label) {
703 Register holder = 736 Register holder =
704 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, 737 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
705 scratch1, scratch2, name, 738 scratch1, scratch2, name,
706 miss_label); 739 miss_label);
707 740
708 __ EnterInternalFrame(); 741 __ EnterInternalFrame();
709 // Save the name_ register across the call. 742 // Save the name_ register across the call.
710 __ push(name_); 743 __ push(name_);
711 744
712 PushInterceptorArguments(masm, 745 PushInterceptorArguments(masm,
713 receiver, 746 receiver,
714 holder, 747 holder,
715 name_, 748 name_,
716 holder_obj); 749 interceptor_holder);
717 750
718 __ CallExternalReference( 751 __ CallExternalReference(
719 ExternalReference( 752 ExternalReference(
720 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), 753 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
721 5); 754 5);
722 755
723 // Restore the name_ register. 756 // Restore the name_ register.
724 __ pop(name_); 757 __ pop(name_);
725 __ LeaveInternalFrame(); 758 __ LeaveInternalFrame();
726 } 759 }
(...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 // Return the generated code. 2417 // Return the generated code.
2385 return GetCode(); 2418 return GetCode();
2386 } 2419 }
2387 2420
2388 2421
2389 #undef __ 2422 #undef __
2390 2423
2391 } } // namespace v8::internal 2424 } } // namespace v8::internal
2392 2425
2393 #endif // V8_TARGET_ARCH_IA32 2426 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698