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

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

Issue 144543004: Reland r18714 'Unify calling to GenerateFastApiCallBody before stubbing it' (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: remove assert Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « src/arm/stub-cache-arm.cc ('k') | src/stub-cache.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 __ CallExternalReference( 411 __ CallExternalReference(
412 ExternalReference(IC_Utility(id), masm->isolate()), 412 ExternalReference(IC_Utility(id), masm->isolate()),
413 StubCache::kInterceptorArgsLength); 413 StubCache::kInterceptorArgsLength);
414 } 414 }
415 415
416 416
417 // Number of pointers to be reserved on stack for fast API call. 417 // Number of pointers to be reserved on stack for fast API call.
418 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; 418 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
419 419
420 420
421 // Reserves space for the extra arguments to API function in the
422 // caller's frame.
423 //
424 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
425 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
426 // ----------- S t a t e -------------
427 // -- esp[0] : return address
428 // -- esp[4] : last argument in the internal frame of the caller
429 // -----------------------------------
430 __ pop(scratch);
431 for (int i = 0; i < kFastApiCallArguments; i++) {
432 __ push(Immediate(Smi::FromInt(0)));
433 }
434 __ push(scratch);
435 }
436
437
438 // Undoes the effects of ReserveSpaceForFastApiCall.
439 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
440 // ----------- S t a t e -------------
441 // -- esp[0] : return address.
442 // -- esp[4] : last fast api call extra argument.
443 // -- ...
444 // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument.
445 // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal
446 // frame.
447 // -----------------------------------
448 __ pop(scratch);
449 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments));
450 __ push(scratch);
451 }
452
453
454 static void GenerateFastApiCallBody(MacroAssembler* masm, 421 static void GenerateFastApiCallBody(MacroAssembler* masm,
455 const CallOptimization& optimization, 422 const CallOptimization& optimization,
456 int argc, 423 int argc,
424 Register holder,
425 Register scratch1,
426 Register scratch2,
427 Register scratch3,
457 bool restore_context); 428 bool restore_context);
458 429
459
460 // Generates call to API function. 430 // Generates call to API function.
461 static void GenerateFastApiCall(MacroAssembler* masm, 431 static void GenerateFastApiCall(MacroAssembler* masm,
462 const CallOptimization& optimization, 432 const CallOptimization& optimization,
463 int argc) { 433 int argc,
464 typedef FunctionCallbackArguments FCA; 434 Handle<Map> map_to_holder,
465 // Save calling context. 435 CallOptimization::HolderLookup holder_lookup) {
466 __ mov(Operand(esp, (1 + FCA::kContextSaveIndex) * kPointerSize), esi); 436 Counters* counters = masm->isolate()->counters();
437 __ IncrementCounter(counters->call_const_fast_api(), 1);
467 438
468 // Get the function and setup the context. 439 // Move holder to a register
469 Handle<JSFunction> function = optimization.constant_function(); 440 Register holder_reg = eax;
470 __ LoadHeapObject(edi, function); 441 switch (holder_lookup) {
471 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 442 case CallOptimization::kHolderIsReceiver:
472 443 {
473 // Construct the FunctionCallbackInfo. 444 ASSERT(map_to_holder.is_null());
474 __ mov(Operand(esp, (1 + FCA::kCalleeIndex) * kPointerSize), edi); 445 __ mov(holder_reg, Operand(esp, (argc + 1)* kPointerSize));
475 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 446 }
476 Handle<Object> call_data(api_call_info->data(), masm->isolate()); 447 break;
477 if (masm->isolate()->heap()->InNewSpace(*call_data)) { 448 case CallOptimization::kHolderIsPrototypeOfMap:
478 __ mov(ecx, api_call_info); 449 {
479 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); 450 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
480 __ mov(Operand(esp, (1 + FCA::kDataIndex) * kPointerSize), ebx); 451 if (!masm->isolate()->heap()->InNewSpace(*holder)) {
481 } else { 452 __ mov(holder_reg, holder);
482 __ mov(Operand(esp, (1 + FCA::kDataIndex) * kPointerSize), 453 } else {
483 Immediate(call_data)); 454 __ mov(holder_reg, map_to_holder);
455 __ mov(holder_reg, FieldOperand(holder_reg, Map::kPrototypeOffset));
456 }
457 }
458 break;
459 case CallOptimization::kHolderNotFound:
460 UNREACHABLE();
484 } 461 }
485 __ mov(Operand(esp, (1 + FCA::kIsolateIndex) * kPointerSize), 462 GenerateFastApiCallBody(masm,
486 Immediate(reinterpret_cast<int>(masm->isolate()))); 463 optimization,
487 __ mov(Operand(esp, (1 + FCA::kReturnValueOffset) * kPointerSize), 464 argc,
488 masm->isolate()->factory()->undefined_value()); 465 holder_reg,
489 __ mov(Operand(esp, (1 + FCA::kReturnValueDefaultValueIndex) * kPointerSize), 466 ebx,
490 masm->isolate()->factory()->undefined_value()); 467 ecx,
491 468 edx,
492 // Prepare arguments. 469 false);
493 STATIC_ASSERT(kFastApiCallArguments == 7);
494 __ lea(eax, Operand(esp, 1 * kPointerSize));
495
496 GenerateFastApiCallBody(masm, optimization, argc, false);
497 } 470 }
498 471
499 472
500 // Generate call to api function. 473 // Generate call to api function.
501 // This function uses push() to generate smaller, faster code than 474 // This function uses push() to generate smaller, faster code than
502 // the version above. It is an optimization that should will be removed 475 // the version above. It is an optimization that should will be removed
503 // when api call ICs are generated in hydrogen. 476 // when api call ICs are generated in hydrogen.
504 static void GenerateFastApiCall(MacroAssembler* masm, 477 static void GenerateFastApiCall(MacroAssembler* masm,
505 const CallOptimization& optimization, 478 const CallOptimization& optimization,
506 Register receiver, 479 Register receiver,
507 Register scratch1, 480 Register scratch1,
508 Register scratch2, 481 Register scratch2,
509 Register scratch3, 482 Register scratch3,
510 int argc, 483 int argc,
511 Register* values) { 484 Register* values) {
512 ASSERT(optimization.is_simple_api_call());
513
514 // Copy return value. 485 // Copy return value.
515 __ pop(scratch1); 486 __ pop(scratch1);
516
517 // receiver 487 // receiver
518 __ push(receiver); 488 __ push(receiver);
519
520 // Write the arguments to stack frame. 489 // Write the arguments to stack frame.
521 for (int i = 0; i < argc; i++) { 490 for (int i = 0; i < argc; i++) {
522 Register arg = values[argc-1-i]; 491 Register arg = values[argc-1-i];
523 ASSERT(!receiver.is(arg)); 492 ASSERT(!receiver.is(arg));
524 ASSERT(!scratch1.is(arg)); 493 ASSERT(!scratch1.is(arg));
525 ASSERT(!scratch2.is(arg)); 494 ASSERT(!scratch2.is(arg));
526 ASSERT(!scratch3.is(arg)); 495 ASSERT(!scratch3.is(arg));
527 __ push(arg); 496 __ push(arg);
528 } 497 }
498 __ push(scratch1);
499 // Stack now matches JSFunction abi.
500 GenerateFastApiCallBody(masm,
501 optimization,
502 argc,
503 receiver,
504 scratch1,
505 scratch2,
506 scratch3,
507 true);
508 }
509
510
511 static void GenerateFastApiCallBody(MacroAssembler* masm,
512 const CallOptimization& optimization,
513 int argc,
514 Register holder,
515 Register scratch1,
516 Register scratch2,
517 Register scratch3,
518 bool restore_context) {
519 // ----------- S t a t e -------------
520 // -- esp[0] : return address
521 // -- esp[4] : last argument
522 // -- ...
523 // -- esp[argc * 4] : first argument
524 // -- esp[(argc + 1) * 4] : receiver
525 ASSERT(optimization.is_simple_api_call());
529 526
530 typedef FunctionCallbackArguments FCA; 527 typedef FunctionCallbackArguments FCA;
531 528
532 STATIC_ASSERT(FCA::kHolderIndex == 0); 529 STATIC_ASSERT(FCA::kHolderIndex == 0);
533 STATIC_ASSERT(FCA::kIsolateIndex == 1); 530 STATIC_ASSERT(FCA::kIsolateIndex == 1);
534 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 531 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
535 STATIC_ASSERT(FCA::kReturnValueOffset == 3); 532 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
536 STATIC_ASSERT(FCA::kDataIndex == 4); 533 STATIC_ASSERT(FCA::kDataIndex == 4);
537 STATIC_ASSERT(FCA::kCalleeIndex == 5); 534 STATIC_ASSERT(FCA::kCalleeIndex == 5);
538 STATIC_ASSERT(FCA::kContextSaveIndex == 6); 535 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
539 STATIC_ASSERT(FCA::kArgsLength == 7); 536 STATIC_ASSERT(FCA::kArgsLength == 7);
540 537
538 __ pop(scratch1);
539
540 ASSERT(!holder.is(esi));
541 // context save 541 // context save
542 __ push(esi); 542 __ push(esi);
543 543
544 // Get the function and setup the context. 544 // Get the function and setup the context.
545 Handle<JSFunction> function = optimization.constant_function(); 545 Handle<JSFunction> function = optimization.constant_function();
546 __ LoadHeapObject(scratch2, function); 546 __ LoadHeapObject(scratch2, function);
547 __ mov(esi, FieldOperand(scratch2, JSFunction::kContextOffset)); 547 __ mov(esi, FieldOperand(scratch2, JSFunction::kContextOffset));
548 // callee 548 // callee
549 __ push(scratch2); 549 __ push(scratch2);
550 550
551 Isolate* isolate = masm->isolate(); 551 Isolate* isolate = masm->isolate();
552 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 552 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
553 Handle<Object> call_data(api_call_info->data(), isolate); 553 Handle<Object> call_data(api_call_info->data(), isolate);
554 // Push data from ExecutableAccessorInfo. 554 // Push data from ExecutableAccessorInfo.
555 if (isolate->heap()->InNewSpace(*call_data)) { 555 if (isolate->heap()->InNewSpace(*call_data)) {
556 __ mov(scratch2, api_call_info); 556 __ mov(scratch2, api_call_info);
557 __ mov(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset)); 557 __ mov(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
558 __ push(scratch3); 558 __ push(scratch3);
559 } else { 559 } else {
560 __ push(Immediate(call_data)); 560 __ push(Immediate(call_data));
561 } 561 }
562 // return value 562 // return value
563 __ push(Immediate(isolate->factory()->undefined_value())); 563 __ push(Immediate(isolate->factory()->undefined_value()));
564 // return value default 564 // return value default
565 __ push(Immediate(isolate->factory()->undefined_value())); 565 __ push(Immediate(isolate->factory()->undefined_value()));
566 // isolate 566 // isolate
567 __ push(Immediate(reinterpret_cast<int>(isolate))); 567 __ push(Immediate(reinterpret_cast<int>(isolate)));
568 // holder 568 // holder
569 __ push(receiver); 569 __ push(holder);
570 570
571 // store receiver address for GenerateFastApiCallBody 571 // store receiver address for GenerateFastApiCallBody
572 ASSERT(!scratch1.is(eax)); 572 ASSERT(!scratch1.is(eax));
573 __ mov(eax, esp); 573 __ mov(eax, esp);
574 574
575 // return address 575 // return address
576 __ push(scratch1); 576 __ push(scratch1);
577 577
578 GenerateFastApiCallBody(masm, optimization, argc, true);
579 }
580
581
582 static void GenerateFastApiCallBody(MacroAssembler* masm,
583 const CallOptimization& optimization,
584 int argc,
585 bool restore_context) {
586 // ----------- S t a t e -------------
587 // -- esp[0] : return address
588 // -- esp[4] - esp[28] : FunctionCallbackInfo, incl.
589 // : object passing the type check
590 // (set by CheckPrototypes)
591 // -- esp[32] : last argument
592 // -- ...
593 // -- esp[(argc + 7) * 4] : first argument
594 // -- esp[(argc + 8) * 4] : receiver
595 //
596 // -- eax : receiver address
597 // -----------------------------------
598 typedef FunctionCallbackArguments FCA;
599
600 // API function gets reference to the v8::Arguments. If CPU profiler 578 // API function gets reference to the v8::Arguments. If CPU profiler
601 // is enabled wrapper function will be called and we need to pass 579 // is enabled wrapper function will be called and we need to pass
602 // address of the callback as additional parameter, always allocate 580 // address of the callback as additional parameter, always allocate
603 // space for it. 581 // space for it.
604 const int kApiArgc = 1 + 1; 582 const int kApiArgc = 1 + 1;
605 583
606 // Allocate the v8::Arguments structure in the arguments' space since 584 // Allocate the v8::Arguments structure in the arguments' space since
607 // it's not controlled by GC. 585 // it's not controlled by GC.
608 const int kApiStackSpace = 4; 586 const int kApiStackSpace = 4;
609 587
610 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
611
612 // Function address is a foreign pointer outside V8's heap. 588 // Function address is a foreign pointer outside V8's heap.
613 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 589 Address function_address = v8::ToCData<Address>(api_call_info->callback());
614 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); 590 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace);
615 591
616 // FunctionCallbackInfo::implicit_args_. 592 // FunctionCallbackInfo::implicit_args_.
617 __ mov(ApiParameterOperand(2), eax); 593 __ mov(ApiParameterOperand(2), eax);
618 __ add(eax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize)); 594 __ add(eax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
619 // FunctionCallbackInfo::values_. 595 // FunctionCallbackInfo::values_.
620 __ mov(ApiParameterOperand(3), eax); 596 __ mov(ApiParameterOperand(3), eax);
621 // FunctionCallbackInfo::length_. 597 // FunctionCallbackInfo::length_.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 Register scratch2, 662 Register scratch2,
687 Register scratch3, 663 Register scratch3,
688 Handle<JSObject> interceptor_holder, 664 Handle<JSObject> interceptor_holder,
689 LookupResult* lookup, 665 LookupResult* lookup,
690 Handle<Name> name, 666 Handle<Name> name,
691 const CallOptimization& optimization, 667 const CallOptimization& optimization,
692 Label* miss_label) { 668 Label* miss_label) {
693 ASSERT(optimization.is_constant_call()); 669 ASSERT(optimization.is_constant_call());
694 ASSERT(!lookup->holder()->IsGlobalObject()); 670 ASSERT(!lookup->holder()->IsGlobalObject());
695 671
696 int depth1 = kInvalidProtoDepth;
697 int depth2 = kInvalidProtoDepth;
698 bool can_do_fast_api_call = false;
699 if (optimization.is_simple_api_call() &&
700 !lookup->holder()->IsGlobalObject()) {
701 depth1 = optimization.GetPrototypeDepthOfExpectedType(
702 object, interceptor_holder);
703 if (depth1 == kInvalidProtoDepth) {
704 depth2 = optimization.GetPrototypeDepthOfExpectedType(
705 interceptor_holder, Handle<JSObject>(lookup->holder()));
706 }
707 can_do_fast_api_call =
708 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
709 }
710
711 Counters* counters = masm->isolate()->counters(); 672 Counters* counters = masm->isolate()->counters();
712 __ IncrementCounter(counters->call_const_interceptor(), 1); 673 __ IncrementCounter(counters->call_const_interceptor(), 1);
713 674
714 if (can_do_fast_api_call) {
715 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
716 ReserveSpaceForFastApiCall(masm, scratch1);
717 }
718
719 // Check that the maps from receiver to interceptor's holder 675 // Check that the maps from receiver to interceptor's holder
720 // haven't changed and thus we can invoke interceptor. 676 // haven't changed and thus we can invoke interceptor.
721 Label miss_cleanup;
722 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
723 Register holder = 677 Register holder =
724 stub_compiler_->CheckPrototypes( 678 stub_compiler_->CheckPrototypes(
725 IC::CurrentTypeOf(object, masm->isolate()), receiver, 679 IC::CurrentTypeOf(object, masm->isolate()), receiver,
726 interceptor_holder, scratch1, scratch2, scratch3, 680 interceptor_holder, scratch1, scratch2, scratch3,
727 name, depth1, miss); 681 name, miss_label);
728 682
729 // Invoke an interceptor and if it provides a value, 683 // Invoke an interceptor and if it provides a value,
730 // branch to |regular_invoke|. 684 // branch to |regular_invoke|.
731 Label regular_invoke; 685 Label regular_invoke;
732 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 686 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
733 &regular_invoke); 687 &regular_invoke);
734 688
735 // Interceptor returned nothing for this property. Try to use cached 689 // Interceptor returned nothing for this property. Try to use cached
736 // constant function. 690 // constant function.
737 691
738 // Check that the maps from interceptor's holder to constant function's 692 // Check that the maps from interceptor's holder to constant function's
739 // holder haven't changed and thus we can use cached constant function. 693 // holder haven't changed and thus we can use cached constant function.
740 if (*interceptor_holder != lookup->holder()) { 694 if (*interceptor_holder != lookup->holder()) {
741 stub_compiler_->CheckPrototypes( 695 stub_compiler_->CheckPrototypes(
742 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, 696 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
743 handle(lookup->holder()), scratch1, scratch2, scratch3, 697 handle(lookup->holder()), scratch1, scratch2, scratch3,
744 name, depth2, miss); 698 name, miss_label);
745 } else { 699 }
746 // CheckPrototypes has a side effect of fetching a 'holder' 700
747 // for API (object which is instanceof for the signature). It's 701 Handle<Map> lookup_map;
748 // safe to omit it here, as if present, it should be fetched 702 CallOptimization::HolderLookup holder_lookup =
749 // by the previous CheckPrototypes. 703 CallOptimization::kHolderNotFound;
750 ASSERT(depth2 == kInvalidProtoDepth); 704 if (optimization.is_simple_api_call() &&
705 !lookup->holder()->IsGlobalObject()) {
706 lookup_map = optimization.LookupHolderOfExpectedType(
707 object, object, interceptor_holder, &holder_lookup);
708 if (holder_lookup == CallOptimization::kHolderNotFound) {
709 lookup_map =
710 optimization.LookupHolderOfExpectedType(
711 object,
712 interceptor_holder,
713 Handle<JSObject>(lookup->holder()),
714 &holder_lookup);
715 }
751 } 716 }
752 717
753 // Invoke function. 718 // Invoke function.
754 if (can_do_fast_api_call) { 719 if (holder_lookup != CallOptimization::kHolderNotFound) {
755 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 720 int argc = arguments_.immediate();
721 GenerateFastApiCall(masm,
722 optimization,
723 argc,
724 lookup_map,
725 holder_lookup);
756 } else { 726 } else {
757 Handle<JSFunction> fun = optimization.constant_function(); 727 Handle<JSFunction> fun = optimization.constant_function();
758 stub_compiler_->GenerateJumpFunction(object, fun); 728 stub_compiler_->GenerateJumpFunction(object, fun);
759 } 729 }
760 730
761 // Deferred code for fast API call case---clean preallocated space.
762 if (can_do_fast_api_call) {
763 __ bind(&miss_cleanup);
764 FreeSpaceForFastApiCall(masm, scratch1);
765 __ jmp(miss_label);
766 }
767
768 // Invoke a regular function. 731 // Invoke a regular function.
769 __ bind(&regular_invoke); 732 __ bind(&regular_invoke);
770 if (can_do_fast_api_call) {
771 FreeSpaceForFastApiCall(masm, scratch1);
772 }
773 } 733 }
774 734
775 void CompileRegular(MacroAssembler* masm, 735 void CompileRegular(MacroAssembler* masm,
776 Handle<JSObject> object, 736 Handle<JSObject> object,
777 Register receiver, 737 Register receiver,
778 Register scratch1, 738 Register scratch1,
779 Register scratch2, 739 Register scratch2,
780 Register scratch3, 740 Register scratch3,
781 Handle<Name> name, 741 Handle<Name> name,
782 Handle<JSObject> interceptor_holder, 742 Handle<JSObject> interceptor_holder,
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
1183 #define __ ACCESS_MASM(masm()) 1143 #define __ ACCESS_MASM(masm())
1184 1144
1185 1145
1186 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, 1146 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
1187 Register object_reg, 1147 Register object_reg,
1188 Handle<JSObject> holder, 1148 Handle<JSObject> holder,
1189 Register holder_reg, 1149 Register holder_reg,
1190 Register scratch1, 1150 Register scratch1,
1191 Register scratch2, 1151 Register scratch2,
1192 Handle<Name> name, 1152 Handle<Name> name,
1193 int save_at_depth,
1194 Label* miss, 1153 Label* miss,
1195 PrototypeCheckType check) { 1154 PrototypeCheckType check) {
1196 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); 1155 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1197 // Make sure that the type feedback oracle harvests the receiver map. 1156 // Make sure that the type feedback oracle harvests the receiver map.
1198 // TODO(svenpanne) Remove this hack when all ICs are reworked. 1157 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1199 __ mov(scratch1, receiver_map); 1158 __ mov(scratch1, receiver_map);
1200 1159
1201 // Make sure there's no overlap between holder and object registers. 1160 // Make sure there's no overlap between holder and object registers.
1202 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 1161 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1203 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1162 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1204 && !scratch2.is(scratch1)); 1163 && !scratch2.is(scratch1));
1205 1164
1206 // Keep track of the current object in register reg. 1165 // Keep track of the current object in register reg.
1207 Register reg = object_reg; 1166 Register reg = object_reg;
1208 int depth = 0; 1167 int depth = 0;
1209 1168
1210 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1;
1211 if (save_at_depth == depth) {
1212 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg);
1213 }
1214
1215 Handle<JSObject> current = Handle<JSObject>::null(); 1169 Handle<JSObject> current = Handle<JSObject>::null();
1216 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); 1170 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1217 Handle<JSObject> prototype = Handle<JSObject>::null(); 1171 Handle<JSObject> prototype = Handle<JSObject>::null();
1218 Handle<Map> current_map = receiver_map; 1172 Handle<Map> current_map = receiver_map;
1219 Handle<Map> holder_map(holder->map()); 1173 Handle<Map> holder_map(holder->map());
1220 // Traverse the prototype chain and check the maps in the prototype chain for 1174 // Traverse the prototype chain and check the maps in the prototype chain for
1221 // fast and global objects or do negative lookup for normal objects. 1175 // fast and global objects or do negative lookup for normal objects.
1222 while (!current_map.is_identical_to(holder_map)) { 1176 while (!current_map.is_identical_to(holder_map)) {
1223 ++depth; 1177 ++depth;
1224 1178
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 if (in_new_space) { 1226 if (in_new_space) {
1273 // The prototype is in new space; we cannot store a reference to it 1227 // The prototype is in new space; we cannot store a reference to it
1274 // in the code. Load it from the map. 1228 // in the code. Load it from the map.
1275 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1229 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1276 } else { 1230 } else {
1277 // The prototype is in old space; load it directly. 1231 // The prototype is in old space; load it directly.
1278 __ mov(reg, prototype); 1232 __ mov(reg, prototype);
1279 } 1233 }
1280 } 1234 }
1281 1235
1282 if (save_at_depth == depth) {
1283 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg);
1284 }
1285
1286 // Go to the next object in the prototype chain. 1236 // Go to the next object in the prototype chain.
1287 current = prototype; 1237 current = prototype;
1288 current_map = handle(current->map()); 1238 current_map = handle(current->map());
1289 } 1239 }
1290 1240
1291 // Log the check depth. 1241 // Log the check depth.
1292 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1242 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1293 1243
1294 if (depth != 0 || check == CHECK_ALL_MAPS) { 1244 if (depth != 0 || check == CHECK_ALL_MAPS) {
1295 // Check the holder map. 1245 // Check the holder map.
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
1672 Handle<JSObject> holder, 1622 Handle<JSObject> holder,
1673 Handle<Cell> cell, 1623 Handle<Cell> cell,
1674 Handle<JSFunction> function, 1624 Handle<JSFunction> function,
1675 Handle<String> name) { 1625 Handle<String> name) {
1676 ASSERT(optimization.is_simple_api_call()); 1626 ASSERT(optimization.is_simple_api_call());
1677 // Bail out if object is a global object as we don't want to 1627 // Bail out if object is a global object as we don't want to
1678 // repatch it to global receiver. 1628 // repatch it to global receiver.
1679 if (object->IsGlobalObject()) return Handle<Code>::null(); 1629 if (object->IsGlobalObject()) return Handle<Code>::null();
1680 if (!cell.is_null()) return Handle<Code>::null(); 1630 if (!cell.is_null()) return Handle<Code>::null();
1681 if (!object->IsJSObject()) return Handle<Code>::null(); 1631 if (!object->IsJSObject()) return Handle<Code>::null();
1682 int depth = optimization.GetPrototypeDepthOfExpectedType( 1632 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1683 Handle<JSObject>::cast(object), holder); 1633 CallOptimization::HolderLookup holder_lookup =
1684 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 1634 CallOptimization::kHolderNotFound;
1635 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1636 receiver, receiver, holder, &holder_lookup);
1637 if (holder_lookup == CallOptimization::kHolderNotFound) {
1638 return Handle<Code>::null();
1639 }
1685 1640
1686 Label miss, miss_before_stack_reserved; 1641 Label miss;
1687 1642 GenerateNameCheck(name, &miss);
1688 GenerateNameCheck(name, &miss_before_stack_reserved);
1689 1643
1690 // Get the receiver from the stack. 1644 // Get the receiver from the stack.
1691 const int argc = arguments().immediate(); 1645 const int argc = arguments().immediate();
1692 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1646 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1693 1647
1694 // Check that the receiver isn't a smi. 1648 // Check that the receiver isn't a smi.
1695 __ JumpIfSmi(edx, &miss_before_stack_reserved); 1649 __ JumpIfSmi(edx, &miss);
1696 1650
1697 Counters* counters = isolate()->counters(); 1651 Counters* counters = isolate()->counters();
1698 __ IncrementCounter(counters->call_const(), 1); 1652 __ IncrementCounter(counters->call_const(), 1);
1699 __ IncrementCounter(counters->call_const_fast_api(), 1);
1700
1701 // Allocate space for v8::Arguments implicit values. Must be initialized
1702 // before calling any runtime function.
1703 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
1704 1653
1705 // Check that the maps haven't changed and find a Holder as a side effect. 1654 // Check that the maps haven't changed and find a Holder as a side effect.
1706 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, 1655 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
1707 ebx, eax, edi, name, depth, &miss); 1656 ebx, eax, edi, name, &miss);
1708 1657
1709 // Move the return address on top of the stack. 1658 GenerateFastApiCall(masm(), optimization, argc, lookup_map, holder_lookup);
1710 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize));
1711 __ mov(Operand(esp, 0 * kPointerSize), eax);
1712 1659
1713 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains 1660 HandlerFrontendFooter(&miss);
1714 // duplicate of return address and will be overwritten.
1715 GenerateFastApiCall(masm(), optimization, argc);
1716
1717 __ bind(&miss);
1718 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
1719
1720 HandlerFrontendFooter(&miss_before_stack_reserved);
1721 1661
1722 // Return the generated code. 1662 // Return the generated code.
1723 return GetCode(function); 1663 return GetCode(function);
1724 } 1664 }
1725 1665
1726 1666
1727 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1667 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1728 Label success; 1668 Label success;
1729 // Check that the object is a boolean. 1669 // Check that the object is a boolean.
1730 __ cmp(object, factory()->true_value()); 1670 __ cmp(object, factory()->true_value());
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
2246 // ----------------------------------- 2186 // -----------------------------------
2247 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2187 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2248 } 2188 }
2249 2189
2250 2190
2251 #undef __ 2191 #undef __
2252 2192
2253 } } // namespace v8::internal 2193 } } // namespace v8::internal
2254 2194
2255 #endif // V8_TARGET_ARCH_IA32 2195 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/arm/stub-cache-arm.cc ('k') | src/stub-cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698