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

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

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