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

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

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