Chromium Code Reviews

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

Issue 142973005: Unify calling to GenerateFastApiCallBody before stubbing it (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: remove MoveHolder Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | 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...)
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 fprintf(stderr, "%s %p %p\n", __func__, *map_to_holder, *holder);
Toon Verwaest 2014/01/21 11:30:59 Remove debugging code.
461 __ movp(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); 428 if (!masm->isolate()->heap()->InNewSpace(*holder)) {
462 __ movp(args.GetArgumentOperand(offset - FCA::kDataIndex), rbx); 429 __ Move(holder_reg, holder);
463 } else { 430 } else {
464 __ Move(args.GetArgumentOperand(offset - FCA::kDataIndex), call_data); 431 __ Move(holder_reg, map_to_holder);
432 __ movp(holder_reg, FieldOperand(holder_reg, Map::kPrototypeOffset));
433 }
434 }
435 break;
436 case CallOptimization::kHolderNotFound:
437 UNREACHABLE();
465 } 438 }
466 __ Move(kScratchRegister, 439 GenerateFastApiCallBody(masm,
467 ExternalReference::isolate_address(masm->isolate())); 440 optimization,
468 __ movp(args.GetArgumentOperand(offset - FCA::kIsolateIndex), 441 argc,
469 kScratchRegister); 442 holder_reg,
470 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 443 rbx,
471 __ movp(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex), 444 rcx,
472 kScratchRegister); 445 rdx,
473 __ movp(args.GetArgumentOperand(offset - FCA::kReturnValueOffset), 446 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 } 447 }
482 448
483 449
484 // Generate call to api function. 450 // Generate call to api function.
485 // This function uses push() to generate smaller, faster code than 451 // This function uses push() to generate smaller, faster code than
486 // the version above. It is an optimization that should will be removed 452 // the version above. It is an optimization that should will be removed
487 // when api call ICs are generated in hydrogen. 453 // when api call ICs are generated in hydrogen.
488 static void GenerateFastApiCall(MacroAssembler* masm, 454 static void GenerateFastApiCall(MacroAssembler* masm,
489 const CallOptimization& optimization, 455 const CallOptimization& optimization,
490 Register receiver, 456 Register receiver,
491 Register scratch1, 457 Register scratch1,
492 Register scratch2, 458 Register scratch2,
493 Register scratch3, 459 Register scratch3,
494 int argc, 460 int argc,
495 Register* values) { 461 Register* values) {
496 ASSERT(optimization.is_simple_api_call());
497
498 __ PopReturnAddressTo(scratch1); 462 __ PopReturnAddressTo(scratch1);
499
500 // receiver 463 // receiver
501 __ push(receiver); 464 __ push(receiver);
502
503 // Write the arguments to stack frame. 465 // Write the arguments to stack frame.
504 for (int i = 0; i < argc; i++) { 466 for (int i = 0; i < argc; i++) {
505 Register arg = values[argc-1-i]; 467 Register arg = values[argc-1-i];
506 ASSERT(!receiver.is(arg)); 468 ASSERT(!receiver.is(arg));
507 ASSERT(!scratch1.is(arg)); 469 ASSERT(!scratch1.is(arg));
508 ASSERT(!scratch2.is(arg)); 470 ASSERT(!scratch2.is(arg));
509 ASSERT(!scratch3.is(arg)); 471 ASSERT(!scratch3.is(arg));
510 __ push(arg); 472 __ push(arg);
511 } 473 }
474 __ PushReturnAddressFrom(scratch1);
475 // Stack now matches JSFunction abi.
476 GenerateFastApiCallBody(masm,
477 optimization,
478 argc,
479 receiver,
480 scratch1,
481 scratch2,
482 scratch3,
483 true);
484 }
485
486
487 static void GenerateFastApiCallBody(MacroAssembler* masm,
488 const CallOptimization& optimization,
489 int argc,
490 Register holder,
491 Register scratch1,
492 Register scratch2,
493 Register scratch3,
494 bool restore_context) {
495 // ----------- S t a t e -------------
496 // -- rsp[0] : return address
497 // -- rsp[8] : last argument
498 // -- ...
499 // -- rsp[argc * 8] : first argument
500 // -- rsp[(argc + 1) * 8] : receiver
501 // -----------------------------------
502 ASSERT(optimization.is_simple_api_call());
512 503
513 typedef FunctionCallbackArguments FCA; 504 typedef FunctionCallbackArguments FCA;
514 505
515 STATIC_ASSERT(FCA::kHolderIndex == 0); 506 STATIC_ASSERT(FCA::kHolderIndex == 0);
516 STATIC_ASSERT(FCA::kIsolateIndex == 1); 507 STATIC_ASSERT(FCA::kIsolateIndex == 1);
517 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 508 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
518 STATIC_ASSERT(FCA::kReturnValueOffset == 3); 509 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
519 STATIC_ASSERT(FCA::kDataIndex == 4); 510 STATIC_ASSERT(FCA::kDataIndex == 4);
520 STATIC_ASSERT(FCA::kCalleeIndex == 5); 511 STATIC_ASSERT(FCA::kCalleeIndex == 5);
521 STATIC_ASSERT(FCA::kContextSaveIndex == 6); 512 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
522 STATIC_ASSERT(FCA::kArgsLength == 7); 513 STATIC_ASSERT(FCA::kArgsLength == 7);
523 514
515 __ PopReturnAddressTo(scratch1);
516
517 ASSERT(!holder.is(rsi));
524 // context save 518 // context save
525 __ push(rsi); 519 __ push(rsi);
526 520
527 // Get the function and setup the context. 521 // Get the function and setup the context.
528 Handle<JSFunction> function = optimization.constant_function(); 522 Handle<JSFunction> function = optimization.constant_function();
529 __ Move(scratch2, function); 523 __ Move(scratch2, function);
530 __ push(scratch2); 524 __ push(scratch2);
531 525
532 Isolate* isolate = masm->isolate(); 526 Isolate* isolate = masm->isolate();
533 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 527 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
(...skipping 16 matching lines...)
550 } 544 }
551 // return value 545 // return value
552 __ push(scratch3); 546 __ push(scratch3);
553 // return value default 547 // return value default
554 __ push(scratch3); 548 __ push(scratch3);
555 // isolate 549 // isolate
556 __ Move(scratch3, 550 __ Move(scratch3,
557 ExternalReference::isolate_address(masm->isolate())); 551 ExternalReference::isolate_address(masm->isolate()));
558 __ push(scratch3); 552 __ push(scratch3);
559 // holder 553 // holder
560 __ push(receiver); 554 __ push(holder);
561 555
562 ASSERT(!scratch1.is(rax)); 556 ASSERT(!scratch1.is(rax));
563 // store receiver address for GenerateFastApiCallBody
564 __ movp(rax, rsp); 557 __ movp(rax, rsp);
558 // Push return address back on stack.
565 __ PushReturnAddressFrom(scratch1); 559 __ PushReturnAddressFrom(scratch1);
566 560
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. 561 // Function address is a foreign pointer outside V8's heap.
591 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 562 Address function_address = v8::ToCData<Address>(api_call_info->callback());
592 563
593 // Allocate the v8::Arguments structure in the arguments' space since 564 // Allocate the v8::Arguments structure in the arguments' space since
594 // it's not controlled by GC. 565 // it's not controlled by GC.
595 const int kApiStackSpace = 4; 566 const int kApiStackSpace = 4;
596 567
597 __ PrepareCallApiFunction(kApiStackSpace); 568 __ PrepareCallApiFunction(kApiStackSpace);
598 569
599 __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_. 570 __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
(...skipping 75 matching lines...)
675 Register scratch2, 646 Register scratch2,
676 Register scratch3, 647 Register scratch3,
677 Handle<JSObject> interceptor_holder, 648 Handle<JSObject> interceptor_holder,
678 LookupResult* lookup, 649 LookupResult* lookup,
679 Handle<Name> name, 650 Handle<Name> name,
680 const CallOptimization& optimization, 651 const CallOptimization& optimization,
681 Label* miss_label) { 652 Label* miss_label) {
682 ASSERT(optimization.is_constant_call()); 653 ASSERT(optimization.is_constant_call());
683 ASSERT(!lookup->holder()->IsGlobalObject()); 654 ASSERT(!lookup->holder()->IsGlobalObject());
684 655
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(); 656 Counters* counters = masm->isolate()->counters();
701 __ IncrementCounter(counters->call_const_interceptor(), 1); 657 __ IncrementCounter(counters->call_const_interceptor(), 1);
702 658
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 659 // Check that the maps from receiver to interceptor's holder
709 // haven't changed and thus we can invoke interceptor. 660 // haven't changed and thus we can invoke interceptor.
710 Label miss_cleanup; 661 Label miss_cleanup;
711 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
712 Register holder = 662 Register holder =
713 stub_compiler_->CheckPrototypes( 663 stub_compiler_->CheckPrototypes(
714 IC::CurrentTypeOf(object, masm->isolate()), receiver, 664 IC::CurrentTypeOf(object, masm->isolate()), receiver,
715 interceptor_holder, scratch1, scratch2, scratch3, 665 interceptor_holder, scratch1, scratch2, scratch3,
716 name, depth1, miss); 666 name, miss_label);
717 667
718 // Invoke an interceptor and if it provides a value, 668 // Invoke an interceptor and if it provides a value,
719 // branch to |regular_invoke|. 669 // branch to |regular_invoke|.
720 Label regular_invoke; 670 Label regular_invoke;
721 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 671 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
722 &regular_invoke); 672 &regular_invoke);
723 673
724 // Interceptor returned nothing for this property. Try to use cached 674 // Interceptor returned nothing for this property. Try to use cached
725 // constant function. 675 // constant function.
726 676
727 // Check that the maps from interceptor's holder to constant function's 677 // 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. 678 // holder haven't changed and thus we can use cached constant function.
729 if (*interceptor_holder != lookup->holder()) { 679 if (*interceptor_holder != lookup->holder()) {
730 stub_compiler_->CheckPrototypes( 680 stub_compiler_->CheckPrototypes(
731 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, 681 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
732 handle(lookup->holder()), scratch1, scratch2, scratch3, 682 handle(lookup->holder()), scratch1, scratch2, scratch3,
733 name, depth2, miss); 683 name, miss_label);
734 } else { 684 }
735 // CheckPrototypes has a side effect of fetching a 'holder' 685
736 // for API (object which is instanceof for the signature). It's 686 Handle<Map> lookup_map;
737 // safe to omit it here, as if present, it should be fetched 687 CallOptimization::HolderLookup holder_lookup =
738 // by the previous CheckPrototypes. 688 CallOptimization::kHolderNotFound;
739 ASSERT(depth2 == kInvalidProtoDepth); 689 if (optimization.is_simple_api_call() &&
690 !lookup->holder()->IsGlobalObject()) {
691 lookup_map = optimization.LookupHolderOfExpectedType(
692 object, object, interceptor_holder, &holder_lookup);
693 if (holder_lookup == CallOptimization::kHolderNotFound) {
694 lookup_map =
695 optimization.LookupHolderOfExpectedType(
696 object,
697 interceptor_holder,
698 Handle<JSObject>(lookup->holder()),
699 &holder_lookup);
700 }
740 } 701 }
741 702
742 // Invoke function. 703 // Invoke function.
743 if (can_do_fast_api_call) { 704 if (holder_lookup != CallOptimization::kHolderNotFound) {
744 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 705 int argc = arguments_.immediate();
706 GenerateFastApiCall(masm,
707 optimization,
708 argc,
709 lookup_map,
710 holder_lookup);
745 } else { 711 } else {
746 Handle<JSFunction> fun = optimization.constant_function(); 712 Handle<JSFunction> fun = optimization.constant_function();
747 stub_compiler_->GenerateJumpFunction(object, fun); 713 stub_compiler_->GenerateJumpFunction(object, fun);
748 } 714 }
749 715
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. 716 // Invoke a regular function.
758 __ bind(&regular_invoke); 717 __ bind(&regular_invoke);
759 if (can_do_fast_api_call) {
760 FreeSpaceForFastApiCall(masm, scratch1);
761 }
762 } 718 }
763 719
764 void CompileRegular(MacroAssembler* masm, 720 void CompileRegular(MacroAssembler* masm,
765 Handle<JSObject> object, 721 Handle<JSObject> object,
766 Register receiver, 722 Register receiver,
767 Register scratch1, 723 Register scratch1,
768 Register scratch2, 724 Register scratch2,
769 Register scratch3, 725 Register scratch3,
770 Handle<Name> name, 726 Handle<Name> name,
771 Handle<JSObject> interceptor_holder, 727 Handle<JSObject> interceptor_holder,
(...skipping 341 matching lines...)
1113 #define __ ACCESS_MASM((masm())) 1069 #define __ ACCESS_MASM((masm()))
1114 1070
1115 1071
1116 Register StubCompiler::CheckPrototypes(Handle<Type> type, 1072 Register StubCompiler::CheckPrototypes(Handle<Type> type,
1117 Register object_reg, 1073 Register object_reg,
1118 Handle<JSObject> holder, 1074 Handle<JSObject> holder,
1119 Register holder_reg, 1075 Register holder_reg,
1120 Register scratch1, 1076 Register scratch1,
1121 Register scratch2, 1077 Register scratch2,
1122 Handle<Name> name, 1078 Handle<Name> name,
1123 int save_at_depth,
1124 Label* miss, 1079 Label* miss,
1125 PrototypeCheckType check) { 1080 PrototypeCheckType check) {
1126 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); 1081 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1127 // Make sure that the type feedback oracle harvests the receiver map. 1082 // Make sure that the type feedback oracle harvests the receiver map.
1128 // TODO(svenpanne) Remove this hack when all ICs are reworked. 1083 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1129 __ Move(scratch1, receiver_map); 1084 __ Move(scratch1, receiver_map);
1130 1085
1131 // Make sure there's no overlap between holder and object registers. 1086 // Make sure there's no overlap between holder and object registers.
1132 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 1087 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1133 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1088 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1134 && !scratch2.is(scratch1)); 1089 && !scratch2.is(scratch1));
1135 1090
1136 // Keep track of the current object in register reg. On the first 1091 // Keep track of the current object in register reg. On the first
1137 // iteration, reg is an alias for object_reg, on later iterations, 1092 // iteration, reg is an alias for object_reg, on later iterations,
1138 // it is an alias for holder_reg. 1093 // it is an alias for holder_reg.
1139 Register reg = object_reg; 1094 Register reg = object_reg;
1140 int depth = 0; 1095 int depth = 0;
1141 1096
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(); 1097 Handle<JSObject> current = Handle<JSObject>::null();
1152 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); 1098 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1153 Handle<JSObject> prototype = Handle<JSObject>::null(); 1099 Handle<JSObject> prototype = Handle<JSObject>::null();
1154 Handle<Map> current_map = receiver_map; 1100 Handle<Map> current_map = receiver_map;
1155 Handle<Map> holder_map(holder->map()); 1101 Handle<Map> holder_map(holder->map());
1156 // Traverse the prototype chain and check the maps in the prototype chain for 1102 // 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. 1103 // fast and global objects or do negative lookup for normal objects.
1158 while (!current_map.is_identical_to(holder_map)) { 1104 while (!current_map.is_identical_to(holder_map)) {
1159 ++depth; 1105 ++depth;
1160 1106
(...skipping 45 matching lines...)
1206 if (in_new_space) { 1152 if (in_new_space) {
1207 // The prototype is in new space; we cannot store a reference to it 1153 // The prototype is in new space; we cannot store a reference to it
1208 // in the code. Load it from the map. 1154 // in the code. Load it from the map.
1209 __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1155 __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1210 } else { 1156 } else {
1211 // The prototype is in old space; load it directly. 1157 // The prototype is in old space; load it directly.
1212 __ Move(reg, prototype); 1158 __ Move(reg, prototype);
1213 } 1159 }
1214 } 1160 }
1215 1161
1216 if (save_at_depth == depth) {
1217 __ movp(args.GetArgumentOperand(kHolderIndex), reg);
1218 }
1219
1220 // Go to the next object in the prototype chain. 1162 // Go to the next object in the prototype chain.
1221 current = prototype; 1163 current = prototype;
1222 current_map = handle(current->map()); 1164 current_map = handle(current->map());
1223 } 1165 }
1224 1166
1225 // Log the check depth. 1167 // Log the check depth.
1226 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1168 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1227 1169
1228 if (depth != 0 || check == CHECK_ALL_MAPS) { 1170 if (depth != 0 || check == CHECK_ALL_MAPS) {
1229 // Check the holder map. 1171 // Check the holder map.
(...skipping 681 matching lines...)
1911 Handle<JSObject> holder, 1853 Handle<JSObject> holder,
1912 Handle<Cell> cell, 1854 Handle<Cell> cell,
1913 Handle<JSFunction> function, 1855 Handle<JSFunction> function,
1914 Handle<String> name) { 1856 Handle<String> name) {
1915 ASSERT(optimization.is_simple_api_call()); 1857 ASSERT(optimization.is_simple_api_call());
1916 // Bail out if object is a global object as we don't want to 1858 // Bail out if object is a global object as we don't want to
1917 // repatch it to global receiver. 1859 // repatch it to global receiver.
1918 if (object->IsGlobalObject()) return Handle<Code>::null(); 1860 if (object->IsGlobalObject()) return Handle<Code>::null();
1919 if (!cell.is_null()) return Handle<Code>::null(); 1861 if (!cell.is_null()) return Handle<Code>::null();
1920 if (!object->IsJSObject()) return Handle<Code>::null(); 1862 if (!object->IsJSObject()) return Handle<Code>::null();
1921 int depth = optimization.GetPrototypeDepthOfExpectedType( 1863 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1922 Handle<JSObject>::cast(object), holder); 1864 CallOptimization::HolderLookup holder_lookup =
1923 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 1865 CallOptimization::kHolderNotFound;
1866 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1867 receiver, receiver, holder, &holder_lookup);
1868 if (holder_lookup == CallOptimization::kHolderNotFound) {
1869 return Handle<Code>::null();
1870 }
1924 1871
1925 Label miss, miss_before_stack_reserved; 1872 Label miss;
1926 GenerateNameCheck(name, &miss_before_stack_reserved); 1873 GenerateNameCheck(name, &miss);
1927 1874
1928 const int argc = arguments().immediate(); 1875 const int argc = arguments().immediate();
1929 StackArgumentsAccessor args(rsp, argc); 1876 StackArgumentsAccessor args(rsp, argc);
1930 __ movp(rdx, args.GetReceiverOperand()); 1877 __ movp(rdx, args.GetReceiverOperand());
1931 1878
1932 // Check that the receiver isn't a smi. 1879 // Check that the receiver isn't a smi.
1933 __ JumpIfSmi(rdx, &miss_before_stack_reserved); 1880 __ JumpIfSmi(rdx, &miss);
1934 1881
1935 Counters* counters = isolate()->counters(); 1882 Counters* counters = isolate()->counters();
1936 __ IncrementCounter(counters->call_const(), 1); 1883 __ IncrementCounter(counters->call_const(), 1);
1937 __ IncrementCounter(counters->call_const_fast_api(), 1);
1938
1939 // Allocate space for v8::Arguments implicit values. Must be initialized
1940 // before calling any runtime function.
1941 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1942 1884
1943 // Check that the maps haven't changed and find a Holder as a side effect. 1885 // Check that the maps haven't changed and find a Holder as a side effect.
1944 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, 1886 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
1945 rbx, rax, rdi, name, depth, &miss); 1887 rbx, rax, rdi, name, &miss);
1946 1888
1947 // Move the return address on top of the stack. 1889 GenerateFastApiCall(masm(), optimization, argc, lookup_map, holder_lookup);
1948 __ movq(rax,
1949 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
1950 __ movq(StackOperandForReturnAddress(0), rax);
1951 1890
1952 GenerateFastApiCall(masm(), optimization, argc); 1891 HandlerFrontendFooter(&miss);
1953
1954 __ bind(&miss);
1955 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1956
1957 HandlerFrontendFooter(&miss_before_stack_reserved);
1958 1892
1959 // Return the generated code. 1893 // Return the generated code.
1960 return GetCode(function); 1894 return GetCode(function);
1961 } 1895 }
1962 1896
1963 1897
1964 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1898 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1965 Label success; 1899 Label success;
1966 // Check that the object is a boolean. 1900 // Check that the object is a boolean.
1967 __ CompareRoot(object, Heap::kTrueValueRootIndex); 1901 __ CompareRoot(object, Heap::kTrueValueRootIndex);
(...skipping 522 matching lines...)
2490 // ----------------------------------- 2424 // -----------------------------------
2491 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2425 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2492 } 2426 }
2493 2427
2494 2428
2495 #undef __ 2429 #undef __
2496 2430
2497 } } // namespace v8::internal 2431 } } // namespace v8::internal
2498 2432
2499 #endif // V8_TARGET_ARCH_X64 2433 #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