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

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

Issue 142973005: Unify calling to GenerateFastApiCallBody before stubbing it (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: arm 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<Type> type, 1146 Register StubCompiler::CheckPrototypes(Handle<Type> 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 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
1987 Handle<JSObject> holder, 1937 Handle<JSObject> holder,
1988 Handle<Cell> cell, 1938 Handle<Cell> cell,
1989 Handle<JSFunction> function, 1939 Handle<JSFunction> function,
1990 Handle<String> name) { 1940 Handle<String> name) {
1991 ASSERT(optimization.is_simple_api_call()); 1941 ASSERT(optimization.is_simple_api_call());
1992 // Bail out if object is a global object as we don't want to 1942 // Bail out if object is a global object as we don't want to
1993 // repatch it to global receiver. 1943 // repatch it to global receiver.
1994 if (object->IsGlobalObject()) return Handle<Code>::null(); 1944 if (object->IsGlobalObject()) return Handle<Code>::null();
1995 if (!cell.is_null()) return Handle<Code>::null(); 1945 if (!cell.is_null()) return Handle<Code>::null();
1996 if (!object->IsJSObject()) return Handle<Code>::null(); 1946 if (!object->IsJSObject()) return Handle<Code>::null();
1997 int depth = optimization.GetPrototypeDepthOfExpectedType( 1947 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1998 Handle<JSObject>::cast(object), holder); 1948 CallOptimization::HolderLookup holder_lookup =
1999 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 1949 CallOptimization::kHolderNotFound;
1950 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1951 receiver, receiver, holder, &holder_lookup);
1952 if (holder_lookup == CallOptimization::kHolderNotFound) {
1953 return Handle<Code>::null();
1954 }
2000 1955
2001 Label miss, miss_before_stack_reserved; 1956 Label miss;
2002 1957 GenerateNameCheck(name, &miss);
2003 GenerateNameCheck(name, &miss_before_stack_reserved);
2004 1958
2005 // Get the receiver from the stack. 1959 // Get the receiver from the stack.
2006 const int argc = arguments().immediate(); 1960 const int argc = arguments().immediate();
2007 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1961 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2008 1962
2009 // Check that the receiver isn't a smi. 1963 // Check that the receiver isn't a smi.
2010 __ JumpIfSmi(edx, &miss_before_stack_reserved); 1964 __ JumpIfSmi(edx, &miss);
2011 1965
2012 Counters* counters = isolate()->counters(); 1966 Counters* counters = isolate()->counters();
2013 __ IncrementCounter(counters->call_const(), 1); 1967 __ IncrementCounter(counters->call_const(), 1);
2014 __ IncrementCounter(counters->call_const_fast_api(), 1);
2015
2016 // Allocate space for v8::Arguments implicit values. Must be initialized
2017 // before calling any runtime function.
2018 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
2019 1968
2020 // Check that the maps haven't changed and find a Holder as a side effect. 1969 // Check that the maps haven't changed and find a Holder as a side effect.
2021 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, 1970 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
2022 ebx, eax, edi, name, depth, &miss); 1971 ebx, eax, edi, name, &miss);
2023 1972
2024 // Move the return address on top of the stack. 1973 GenerateFastApiCall(masm(), optimization, argc, lookup_map, holder_lookup);
2025 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize));
2026 __ mov(Operand(esp, 0 * kPointerSize), eax);
2027 1974
2028 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains 1975 HandlerFrontendFooter(&miss);
2029 // duplicate of return address and will be overwritten.
2030 GenerateFastApiCall(masm(), optimization, argc);
2031
2032 __ bind(&miss);
2033 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
2034
2035 HandlerFrontendFooter(&miss_before_stack_reserved);
2036 1976
2037 // Return the generated code. 1977 // Return the generated code.
2038 return GetCode(function); 1978 return GetCode(function);
2039 } 1979 }
2040 1980
2041 1981
2042 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1982 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
2043 Label success; 1983 Label success;
2044 // Check that the object is a boolean. 1984 // Check that the object is a boolean.
2045 __ cmp(object, factory()->true_value()); 1985 __ cmp(object, factory()->true_value());
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
2561 // ----------------------------------- 2501 // -----------------------------------
2562 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2502 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2563 } 2503 }
2564 2504
2565 2505
2566 #undef __ 2506 #undef __
2567 2507
2568 } } // namespace v8::internal 2508 } } // namespace v8::internal
2569 2509
2570 #endif // V8_TARGET_ARCH_IA32 2510 #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