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

Side by Side Diff: src/x64/stub-cache-x64.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/stub-cache.cc ('k') | no next file » | 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 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 __ CallExternalReference( 385 __ CallExternalReference(
386 ExternalReference(IC_Utility(id), masm->isolate()), 386 ExternalReference(IC_Utility(id), masm->isolate()),
387 StubCache::kInterceptorArgsLength); 387 StubCache::kInterceptorArgsLength);
388 } 388 }
389 389
390 390
391 // Number of pointers to be reserved on stack for fast API call. 391 // Number of pointers to be reserved on stack for fast API call.
392 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; 392 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
393 393
394 394
395 // Reserves space for the extra arguments to API function in the
396 // caller's frame.
397 //
398 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
399 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
400 // ----------- S t a t e -------------
401 // -- rsp[0] : return address
402 // -- rsp[8] : last argument in the internal frame of the caller
403 // -----------------------------------
404 __ movq(scratch, StackOperandForReturnAddress(0));
405 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
406 __ movq(StackOperandForReturnAddress(0), scratch);
407 __ Move(scratch, Smi::FromInt(0));
408 StackArgumentsAccessor args(rsp, kFastApiCallArguments,
409 ARGUMENTS_DONT_CONTAIN_RECEIVER);
410 for (int i = 0; i < kFastApiCallArguments; i++) {
411 __ movp(args.GetArgumentOperand(i), scratch);
412 }
413 }
414
415
416 // Undoes the effects of ReserveSpaceForFastApiCall.
417 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
418 // ----------- S t a t e -------------
419 // -- rsp[0] : return address.
420 // -- rsp[8] : last fast api call extra argument.
421 // -- ...
422 // -- rsp[kFastApiCallArguments * 8] : first fast api call extra
423 // argument.
424 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
425 // frame.
426 // -----------------------------------
427 __ movq(scratch, StackOperandForReturnAddress(0));
428 __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize),
429 scratch);
430 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
431 }
432
433
395 static void GenerateFastApiCallBody(MacroAssembler* masm, 434 static void GenerateFastApiCallBody(MacroAssembler* masm,
396 const CallOptimization& optimization, 435 const CallOptimization& optimization,
397 int argc, 436 int argc,
398 Register holder,
399 Register scratch1,
400 Register scratch2,
401 Register scratch3,
402 bool restore_context); 437 bool restore_context);
403 438
404 439
405 // Generates call to API function. 440 // Generates call to API function.
406 static void GenerateFastApiCall(MacroAssembler* masm, 441 static void GenerateFastApiCall(MacroAssembler* masm,
407 const CallOptimization& optimization, 442 const CallOptimization& optimization,
408 int argc, 443 int argc) {
409 Handle<Map> map_to_holder, 444 typedef FunctionCallbackArguments FCA;
410 CallOptimization::HolderLookup holder_lookup) { 445 StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments);
411 Counters* counters = masm->isolate()->counters();
412 __ IncrementCounter(counters->call_const_fast_api(), 1);
413 446
414 // Move holder to a register 447 // Save calling context.
415 Register holder_reg = rax; 448 int offset = argc + kFastApiCallArguments;
416 switch (holder_lookup) { 449 __ movp(args.GetArgumentOperand(offset - FCA::kContextSaveIndex), rsi);
417 case CallOptimization::kHolderIsReceiver: 450
418 { 451 // Get the function and setup the context.
419 ASSERT(map_to_holder.is_null()); 452 Handle<JSFunction> function = optimization.constant_function();
420 StackArgumentsAccessor args(rsp, argc); 453 __ Move(rdi, function);
421 __ movp(holder_reg, args.GetReceiverOperand()); 454 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
422 } 455 // Construct the FunctionCallbackInfo on the stack.
423 break; 456 __ movp(args.GetArgumentOperand(offset - FCA::kCalleeIndex), rdi);
424 case CallOptimization::kHolderIsPrototypeOfMap: 457 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
425 { 458 Handle<Object> call_data(api_call_info->data(), masm->isolate());
426 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype())); 459 if (masm->isolate()->heap()->InNewSpace(*call_data)) {
427 if (!masm->isolate()->heap()->InNewSpace(*holder)) { 460 __ Move(rcx, api_call_info);
428 __ Move(holder_reg, holder); 461 __ movp(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
429 } else { 462 __ movp(args.GetArgumentOperand(offset - FCA::kDataIndex), rbx);
430 __ Move(holder_reg, map_to_holder); 463 } else {
431 __ movp(holder_reg, FieldOperand(holder_reg, Map::kPrototypeOffset)); 464 __ Move(args.GetArgumentOperand(offset - FCA::kDataIndex), call_data);
432 }
433 }
434 break;
435 case CallOptimization::kHolderNotFound:
436 UNREACHABLE();
437 } 465 }
438 GenerateFastApiCallBody(masm, 466 __ Move(kScratchRegister,
439 optimization, 467 ExternalReference::isolate_address(masm->isolate()));
440 argc, 468 __ movp(args.GetArgumentOperand(offset - FCA::kIsolateIndex),
441 holder_reg, 469 kScratchRegister);
442 rbx, 470 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
443 rcx, 471 __ movp(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex),
444 rdx, 472 kScratchRegister);
445 false); 473 __ movp(args.GetArgumentOperand(offset - FCA::kReturnValueOffset),
474 kScratchRegister);
475
476 // Prepare arguments.
477 STATIC_ASSERT(kFastApiCallArguments == 7);
478 __ lea(rax, args.GetArgumentOperand(offset - FCA::kHolderIndex));
479
480 GenerateFastApiCallBody(masm, optimization, argc, false);
446 } 481 }
447 482
448 483
449 // Generate call to api function. 484 // Generate call to api function.
450 // This function uses push() to generate smaller, faster code than 485 // This function uses push() to generate smaller, faster code than
451 // the version above. It is an optimization that should will be removed 486 // the version above. It is an optimization that should will be removed
452 // when api call ICs are generated in hydrogen. 487 // when api call ICs are generated in hydrogen.
453 static void GenerateFastApiCall(MacroAssembler* masm, 488 static void GenerateFastApiCall(MacroAssembler* masm,
454 const CallOptimization& optimization, 489 const CallOptimization& optimization,
455 Register receiver, 490 Register receiver,
456 Register scratch1, 491 Register scratch1,
457 Register scratch2, 492 Register scratch2,
458 Register scratch3, 493 Register scratch3,
459 int argc, 494 int argc,
460 Register* values) { 495 Register* values) {
496 ASSERT(optimization.is_simple_api_call());
497
461 __ PopReturnAddressTo(scratch1); 498 __ PopReturnAddressTo(scratch1);
499
462 // receiver 500 // receiver
463 __ push(receiver); 501 __ push(receiver);
502
464 // Write the arguments to stack frame. 503 // Write the arguments to stack frame.
465 for (int i = 0; i < argc; i++) { 504 for (int i = 0; i < argc; i++) {
466 Register arg = values[argc-1-i]; 505 Register arg = values[argc-1-i];
467 ASSERT(!receiver.is(arg)); 506 ASSERT(!receiver.is(arg));
468 ASSERT(!scratch1.is(arg)); 507 ASSERT(!scratch1.is(arg));
469 ASSERT(!scratch2.is(arg)); 508 ASSERT(!scratch2.is(arg));
470 ASSERT(!scratch3.is(arg)); 509 ASSERT(!scratch3.is(arg));
471 __ push(arg); 510 __ push(arg);
472 } 511 }
473 __ PushReturnAddressFrom(scratch1);
474 // Stack now matches JSFunction abi.
475 GenerateFastApiCallBody(masm,
476 optimization,
477 argc,
478 receiver,
479 scratch1,
480 scratch2,
481 scratch3,
482 true);
483 }
484
485
486 static void GenerateFastApiCallBody(MacroAssembler* masm,
487 const CallOptimization& optimization,
488 int argc,
489 Register holder,
490 Register scratch1,
491 Register scratch2,
492 Register scratch3,
493 bool restore_context) {
494 // ----------- S t a t e -------------
495 // -- rsp[0] : return address
496 // -- rsp[8] : last argument
497 // -- ...
498 // -- rsp[argc * 8] : first argument
499 // -- rsp[(argc + 1) * 8] : receiver
500 // -----------------------------------
501 ASSERT(optimization.is_simple_api_call());
502 512
503 typedef FunctionCallbackArguments FCA; 513 typedef FunctionCallbackArguments FCA;
504 514
505 STATIC_ASSERT(FCA::kHolderIndex == 0); 515 STATIC_ASSERT(FCA::kHolderIndex == 0);
506 STATIC_ASSERT(FCA::kIsolateIndex == 1); 516 STATIC_ASSERT(FCA::kIsolateIndex == 1);
507 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 517 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
508 STATIC_ASSERT(FCA::kReturnValueOffset == 3); 518 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
509 STATIC_ASSERT(FCA::kDataIndex == 4); 519 STATIC_ASSERT(FCA::kDataIndex == 4);
510 STATIC_ASSERT(FCA::kCalleeIndex == 5); 520 STATIC_ASSERT(FCA::kCalleeIndex == 5);
511 STATIC_ASSERT(FCA::kContextSaveIndex == 6); 521 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
512 STATIC_ASSERT(FCA::kArgsLength == 7); 522 STATIC_ASSERT(FCA::kArgsLength == 7);
513 523
514 __ PopReturnAddressTo(scratch1);
515
516 ASSERT(!holder.is(rsi));
517 // context save 524 // context save
518 __ push(rsi); 525 __ push(rsi);
519 526
520 // Get the function and setup the context. 527 // Get the function and setup the context.
521 Handle<JSFunction> function = optimization.constant_function(); 528 Handle<JSFunction> function = optimization.constant_function();
522 __ Move(scratch2, function); 529 __ Move(scratch2, function);
523 __ push(scratch2); 530 __ push(scratch2);
524 531
525 Isolate* isolate = masm->isolate(); 532 Isolate* isolate = masm->isolate();
526 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 533 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
(...skipping 16 matching lines...) Expand all
543 } 550 }
544 // return value 551 // return value
545 __ push(scratch3); 552 __ push(scratch3);
546 // return value default 553 // return value default
547 __ push(scratch3); 554 __ push(scratch3);
548 // isolate 555 // isolate
549 __ Move(scratch3, 556 __ Move(scratch3,
550 ExternalReference::isolate_address(masm->isolate())); 557 ExternalReference::isolate_address(masm->isolate()));
551 __ push(scratch3); 558 __ push(scratch3);
552 // holder 559 // holder
553 __ push(holder); 560 __ push(receiver);
554 561
555 ASSERT(!scratch1.is(rax)); 562 ASSERT(!scratch1.is(rax));
563 // store receiver address for GenerateFastApiCallBody
556 __ movp(rax, rsp); 564 __ movp(rax, rsp);
557 // Push return address back on stack.
558 __ PushReturnAddressFrom(scratch1); 565 __ PushReturnAddressFrom(scratch1);
559 566
567 GenerateFastApiCallBody(masm, optimization, argc, true);
568 }
569
570
571 static void GenerateFastApiCallBody(MacroAssembler* masm,
572 const CallOptimization& optimization,
573 int argc,
574 bool restore_context) {
575 // ----------- S t a t e -------------
576 // -- rsp[0] : return address
577 // -- rsp[8] - rsp[56] : FunctionCallbackInfo, incl.
578 // : object passing the type check
579 // (set by CheckPrototypes)
580 // -- rsp[64] : last argument
581 // -- ...
582 // -- rsp[(argc + 7) * 8] : first argument
583 // -- rsp[(argc + 8) * 8] : receiver
584 //
585 // rax : receiver address
586 // -----------------------------------
587 typedef FunctionCallbackArguments FCA;
588
589 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
560 // Function address is a foreign pointer outside V8's heap. 590 // Function address is a foreign pointer outside V8's heap.
561 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 591 Address function_address = v8::ToCData<Address>(api_call_info->callback());
562 592
563 // Allocate the v8::Arguments structure in the arguments' space since 593 // Allocate the v8::Arguments structure in the arguments' space since
564 // it's not controlled by GC. 594 // it's not controlled by GC.
565 const int kApiStackSpace = 4; 595 const int kApiStackSpace = 4;
566 596
567 __ PrepareCallApiFunction(kApiStackSpace); 597 __ PrepareCallApiFunction(kApiStackSpace);
568 598
569 __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_. 599 __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 Register scratch2, 675 Register scratch2,
646 Register scratch3, 676 Register scratch3,
647 Handle<JSObject> interceptor_holder, 677 Handle<JSObject> interceptor_holder,
648 LookupResult* lookup, 678 LookupResult* lookup,
649 Handle<Name> name, 679 Handle<Name> name,
650 const CallOptimization& optimization, 680 const CallOptimization& optimization,
651 Label* miss_label) { 681 Label* miss_label) {
652 ASSERT(optimization.is_constant_call()); 682 ASSERT(optimization.is_constant_call());
653 ASSERT(!lookup->holder()->IsGlobalObject()); 683 ASSERT(!lookup->holder()->IsGlobalObject());
654 684
685 int depth1 = kInvalidProtoDepth;
686 int depth2 = kInvalidProtoDepth;
687 bool can_do_fast_api_call = false;
688 if (optimization.is_simple_api_call() &&
689 !lookup->holder()->IsGlobalObject()) {
690 depth1 = optimization.GetPrototypeDepthOfExpectedType(
691 object, interceptor_holder);
692 if (depth1 == kInvalidProtoDepth) {
693 depth2 = optimization.GetPrototypeDepthOfExpectedType(
694 interceptor_holder, Handle<JSObject>(lookup->holder()));
695 }
696 can_do_fast_api_call =
697 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
698 }
699
655 Counters* counters = masm->isolate()->counters(); 700 Counters* counters = masm->isolate()->counters();
656 __ IncrementCounter(counters->call_const_interceptor(), 1); 701 __ IncrementCounter(counters->call_const_interceptor(), 1);
657 702
703 if (can_do_fast_api_call) {
704 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
705 ReserveSpaceForFastApiCall(masm, scratch1);
706 }
707
658 // Check that the maps from receiver to interceptor's holder 708 // Check that the maps from receiver to interceptor's holder
659 // haven't changed and thus we can invoke interceptor. 709 // haven't changed and thus we can invoke interceptor.
660 Label miss_cleanup; 710 Label miss_cleanup;
711 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
661 Register holder = 712 Register holder =
662 stub_compiler_->CheckPrototypes( 713 stub_compiler_->CheckPrototypes(
663 IC::CurrentTypeOf(object, masm->isolate()), receiver, 714 IC::CurrentTypeOf(object, masm->isolate()), receiver,
664 interceptor_holder, scratch1, scratch2, scratch3, 715 interceptor_holder, scratch1, scratch2, scratch3,
665 name, miss_label); 716 name, depth1, miss);
666 717
667 // Invoke an interceptor and if it provides a value, 718 // Invoke an interceptor and if it provides a value,
668 // branch to |regular_invoke|. 719 // branch to |regular_invoke|.
669 Label regular_invoke; 720 Label regular_invoke;
670 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 721 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
671 &regular_invoke); 722 &regular_invoke);
672 723
673 // Interceptor returned nothing for this property. Try to use cached 724 // Interceptor returned nothing for this property. Try to use cached
674 // constant function. 725 // constant function.
675 726
676 // Check that the maps from interceptor's holder to constant function's 727 // Check that the maps from interceptor's holder to constant function's
677 // holder haven't changed and thus we can use cached constant function. 728 // holder haven't changed and thus we can use cached constant function.
678 if (*interceptor_holder != lookup->holder()) { 729 if (*interceptor_holder != lookup->holder()) {
679 stub_compiler_->CheckPrototypes( 730 stub_compiler_->CheckPrototypes(
680 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, 731 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
681 handle(lookup->holder()), scratch1, scratch2, scratch3, 732 handle(lookup->holder()), scratch1, scratch2, scratch3,
682 name, miss_label); 733 name, depth2, miss);
683 } 734 } else {
684 735 // CheckPrototypes has a side effect of fetching a 'holder'
685 Handle<Map> lookup_map; 736 // for API (object which is instanceof for the signature). It's
686 CallOptimization::HolderLookup holder_lookup = 737 // safe to omit it here, as if present, it should be fetched
687 CallOptimization::kHolderNotFound; 738 // by the previous CheckPrototypes.
688 if (optimization.is_simple_api_call() && 739 ASSERT(depth2 == kInvalidProtoDepth);
689 !lookup->holder()->IsGlobalObject()) {
690 lookup_map = optimization.LookupHolderOfExpectedType(
691 object, object, interceptor_holder, &holder_lookup);
692 if (holder_lookup == CallOptimization::kHolderNotFound) {
693 lookup_map =
694 optimization.LookupHolderOfExpectedType(
695 object,
696 interceptor_holder,
697 Handle<JSObject>(lookup->holder()),
698 &holder_lookup);
699 }
700 } 740 }
701 741
702 // Invoke function. 742 // Invoke function.
703 if (holder_lookup != CallOptimization::kHolderNotFound) { 743 if (can_do_fast_api_call) {
704 int argc = arguments_.immediate(); 744 GenerateFastApiCall(masm, optimization, arguments_.immediate());
705 GenerateFastApiCall(masm,
706 optimization,
707 argc,
708 lookup_map,
709 holder_lookup);
710 } else { 745 } else {
711 Handle<JSFunction> fun = optimization.constant_function(); 746 Handle<JSFunction> fun = optimization.constant_function();
712 stub_compiler_->GenerateJumpFunction(object, fun); 747 stub_compiler_->GenerateJumpFunction(object, fun);
713 } 748 }
714 749
750 // Deferred code for fast API call case---clean preallocated space.
751 if (can_do_fast_api_call) {
752 __ bind(&miss_cleanup);
753 FreeSpaceForFastApiCall(masm, scratch1);
754 __ jmp(miss_label);
755 }
756
715 // Invoke a regular function. 757 // Invoke a regular function.
716 __ bind(&regular_invoke); 758 __ bind(&regular_invoke);
759 if (can_do_fast_api_call) {
760 FreeSpaceForFastApiCall(masm, scratch1);
761 }
717 } 762 }
718 763
719 void CompileRegular(MacroAssembler* masm, 764 void CompileRegular(MacroAssembler* masm,
720 Handle<JSObject> object, 765 Handle<JSObject> object,
721 Register receiver, 766 Register receiver,
722 Register scratch1, 767 Register scratch1,
723 Register scratch2, 768 Register scratch2,
724 Register scratch3, 769 Register scratch3,
725 Handle<Name> name, 770 Handle<Name> name,
726 Handle<JSObject> interceptor_holder, 771 Handle<JSObject> interceptor_holder,
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 #define __ ACCESS_MASM((masm())) 1113 #define __ ACCESS_MASM((masm()))
1069 1114
1070 1115
1071 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, 1116 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
1072 Register object_reg, 1117 Register object_reg,
1073 Handle<JSObject> holder, 1118 Handle<JSObject> holder,
1074 Register holder_reg, 1119 Register holder_reg,
1075 Register scratch1, 1120 Register scratch1,
1076 Register scratch2, 1121 Register scratch2,
1077 Handle<Name> name, 1122 Handle<Name> name,
1123 int save_at_depth,
1078 Label* miss, 1124 Label* miss,
1079 PrototypeCheckType check) { 1125 PrototypeCheckType check) {
1080 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); 1126 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1081 // Make sure that the type feedback oracle harvests the receiver map. 1127 // Make sure that the type feedback oracle harvests the receiver map.
1082 // TODO(svenpanne) Remove this hack when all ICs are reworked. 1128 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1083 __ Move(scratch1, receiver_map); 1129 __ Move(scratch1, receiver_map);
1084 1130
1085 // Make sure there's no overlap between holder and object registers. 1131 // Make sure there's no overlap between holder and object registers.
1086 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 1132 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1087 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1133 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1088 && !scratch2.is(scratch1)); 1134 && !scratch2.is(scratch1));
1089 1135
1090 // Keep track of the current object in register reg. On the first 1136 // Keep track of the current object in register reg. On the first
1091 // iteration, reg is an alias for object_reg, on later iterations, 1137 // iteration, reg is an alias for object_reg, on later iterations,
1092 // it is an alias for holder_reg. 1138 // it is an alias for holder_reg.
1093 Register reg = object_reg; 1139 Register reg = object_reg;
1094 int depth = 0; 1140 int depth = 0;
1095 1141
1142 StackArgumentsAccessor args(rsp, kFastApiCallArguments,
1143 ARGUMENTS_DONT_CONTAIN_RECEIVER);
1144 const int kHolderIndex = kFastApiCallArguments - 1 -
1145 FunctionCallbackArguments::kHolderIndex;
1146
1147 if (save_at_depth == depth) {
1148 __ movp(args.GetArgumentOperand(kHolderIndex), object_reg);
1149 }
1150
1096 Handle<JSObject> current = Handle<JSObject>::null(); 1151 Handle<JSObject> current = Handle<JSObject>::null();
1097 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); 1152 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1098 Handle<JSObject> prototype = Handle<JSObject>::null(); 1153 Handle<JSObject> prototype = Handle<JSObject>::null();
1099 Handle<Map> current_map = receiver_map; 1154 Handle<Map> current_map = receiver_map;
1100 Handle<Map> holder_map(holder->map()); 1155 Handle<Map> holder_map(holder->map());
1101 // Traverse the prototype chain and check the maps in the prototype chain for 1156 // Traverse the prototype chain and check the maps in the prototype chain for
1102 // fast and global objects or do negative lookup for normal objects. 1157 // fast and global objects or do negative lookup for normal objects.
1103 while (!current_map.is_identical_to(holder_map)) { 1158 while (!current_map.is_identical_to(holder_map)) {
1104 ++depth; 1159 ++depth;
1105 1160
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 if (in_new_space) { 1206 if (in_new_space) {
1152 // The prototype is in new space; we cannot store a reference to it 1207 // The prototype is in new space; we cannot store a reference to it
1153 // in the code. Load it from the map. 1208 // in the code. Load it from the map.
1154 __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1209 __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1155 } else { 1210 } else {
1156 // The prototype is in old space; load it directly. 1211 // The prototype is in old space; load it directly.
1157 __ Move(reg, prototype); 1212 __ Move(reg, prototype);
1158 } 1213 }
1159 } 1214 }
1160 1215
1216 if (save_at_depth == depth) {
1217 __ movp(args.GetArgumentOperand(kHolderIndex), reg);
1218 }
1219
1161 // Go to the next object in the prototype chain. 1220 // Go to the next object in the prototype chain.
1162 current = prototype; 1221 current = prototype;
1163 current_map = handle(current->map()); 1222 current_map = handle(current->map());
1164 } 1223 }
1165 1224
1166 // Log the check depth. 1225 // Log the check depth.
1167 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1226 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1168 1227
1169 if (depth != 0 || check == CHECK_ALL_MAPS) { 1228 if (depth != 0 || check == CHECK_ALL_MAPS) {
1170 // Check the holder map. 1229 // Check the holder map.
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
1540 Handle<JSObject> holder, 1599 Handle<JSObject> holder,
1541 Handle<Cell> cell, 1600 Handle<Cell> cell,
1542 Handle<JSFunction> function, 1601 Handle<JSFunction> function,
1543 Handle<String> name) { 1602 Handle<String> name) {
1544 ASSERT(optimization.is_simple_api_call()); 1603 ASSERT(optimization.is_simple_api_call());
1545 // Bail out if object is a global object as we don't want to 1604 // Bail out if object is a global object as we don't want to
1546 // repatch it to global receiver. 1605 // repatch it to global receiver.
1547 if (object->IsGlobalObject()) return Handle<Code>::null(); 1606 if (object->IsGlobalObject()) return Handle<Code>::null();
1548 if (!cell.is_null()) return Handle<Code>::null(); 1607 if (!cell.is_null()) return Handle<Code>::null();
1549 if (!object->IsJSObject()) return Handle<Code>::null(); 1608 if (!object->IsJSObject()) return Handle<Code>::null();
1550 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1609 int depth = optimization.GetPrototypeDepthOfExpectedType(
1551 CallOptimization::HolderLookup holder_lookup = 1610 Handle<JSObject>::cast(object), holder);
1552 CallOptimization::kHolderNotFound; 1611 if (depth == kInvalidProtoDepth) return Handle<Code>::null();
1553 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1554 receiver, receiver, holder, &holder_lookup);
1555 if (holder_lookup == CallOptimization::kHolderNotFound) {
1556 return Handle<Code>::null();
1557 }
1558 1612
1559 Label miss; 1613 Label miss, miss_before_stack_reserved;
1560 GenerateNameCheck(name, &miss); 1614 GenerateNameCheck(name, &miss_before_stack_reserved);
1561 1615
1562 const int argc = arguments().immediate(); 1616 const int argc = arguments().immediate();
1563 StackArgumentsAccessor args(rsp, argc); 1617 StackArgumentsAccessor args(rsp, argc);
1564 __ movp(rdx, args.GetReceiverOperand()); 1618 __ movp(rdx, args.GetReceiverOperand());
1565 1619
1566 // Check that the receiver isn't a smi. 1620 // Check that the receiver isn't a smi.
1567 __ JumpIfSmi(rdx, &miss); 1621 __ JumpIfSmi(rdx, &miss_before_stack_reserved);
1568 1622
1569 Counters* counters = isolate()->counters(); 1623 Counters* counters = isolate()->counters();
1570 __ IncrementCounter(counters->call_const(), 1); 1624 __ IncrementCounter(counters->call_const(), 1);
1625 __ IncrementCounter(counters->call_const_fast_api(), 1);
1626
1627 // Allocate space for v8::Arguments implicit values. Must be initialized
1628 // before calling any runtime function.
1629 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1571 1630
1572 // Check that the maps haven't changed and find a Holder as a side effect. 1631 // Check that the maps haven't changed and find a Holder as a side effect.
1573 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, 1632 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
1574 rbx, rax, rdi, name, &miss); 1633 rbx, rax, rdi, name, depth, &miss);
1575 1634
1576 GenerateFastApiCall(masm(), optimization, argc, lookup_map, holder_lookup); 1635 // Move the return address on top of the stack.
1636 __ movq(rax,
1637 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
1638 __ movq(StackOperandForReturnAddress(0), rax);
1577 1639
1578 HandlerFrontendFooter(&miss); 1640 GenerateFastApiCall(masm(), optimization, argc);
1641
1642 __ bind(&miss);
1643 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1644
1645 HandlerFrontendFooter(&miss_before_stack_reserved);
1579 1646
1580 // Return the generated code. 1647 // Return the generated code.
1581 return GetCode(function); 1648 return GetCode(function);
1582 } 1649 }
1583 1650
1584 1651
1585 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1652 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1586 Label success; 1653 Label success;
1587 // Check that the object is a boolean. 1654 // Check that the object is a boolean.
1588 __ CompareRoot(object, Heap::kTrueValueRootIndex); 1655 __ CompareRoot(object, Heap::kTrueValueRootIndex);
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
2111 // ----------------------------------- 2178 // -----------------------------------
2112 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2179 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2113 } 2180 }
2114 2181
2115 2182
2116 #undef __ 2183 #undef __
2117 2184
2118 } } // namespace v8::internal 2185 } } // namespace v8::internal
2119 2186
2120 #endif // V8_TARGET_ARCH_X64 2187 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/stub-cache.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698