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

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: 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
405 static void MoveHolder(MacroAssembler* masm,
406 Handle<JSObject> receiver,
407 Handle<JSObject> holder,
408 Register dest) {
409 ASSERT(!receiver.is_identical_to(holder));
410 if (!masm->isolate()->heap()->InNewSpace(*holder)) {
411 __ Move(dest, holder);
412 return;
413 }
414 Handle<Map> current_map(receiver->map());
415 Handle<Map> holder_map(holder->map());
416 while (!current_map.is_identical_to(holder_map)) {
417 Handle<Map>
Toon Verwaest 2014/01/20 19:11:09 Handle<Map> prototype_map( JSObject::cast(curr
418 prototype_map(JSObject::cast(current_map->prototype())->map());
419 if (prototype_map.is_identical_to(holder_map)) {
420 __ Move(dest, current_map);
421 __ movp(dest, FieldOperand(dest, Map::kPrototypeOffset));
422 return;
423 }
424 current_map = prototype_map;
425 }
426 CHECK(false);
Toon Verwaest 2014/01/20 19:11:09 UNREACHABLE();
427 }
428
429
440 // Generates call to API function. 430 // Generates call to API function.
441 static void GenerateFastApiCall(MacroAssembler* masm, 431 static void GenerateFastApiCall(MacroAssembler* masm,
442 const CallOptimization& optimization, 432 const CallOptimization& optimization,
443 int argc) { 433 int argc,
444 typedef FunctionCallbackArguments FCA; 434 Handle<JSObject> api_receiver,
445 StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments); 435 Handle<JSObject> api_holder) {
436 Counters* counters = masm->isolate()->counters();
437 __ IncrementCounter(counters->call_const_fast_api(), 1);
446 438
447 // Save calling context. 439 Register holder = rax;
448 int offset = argc + kFastApiCallArguments; 440 if (api_holder.is_identical_to(api_receiver)) {
449 __ movp(args.GetArgumentOperand(offset - FCA::kContextSaveIndex), rsi); 441 StackArgumentsAccessor args(rsp, argc);
450 442 __ movp(holder, args.GetReceiverOperand());
451 // Get the function and setup the context.
452 Handle<JSFunction> function = optimization.constant_function();
453 __ Move(rdi, function);
454 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
455 // Construct the FunctionCallbackInfo on the stack.
456 __ movp(args.GetArgumentOperand(offset - FCA::kCalleeIndex), rdi);
457 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
458 Handle<Object> call_data(api_call_info->data(), masm->isolate());
459 if (masm->isolate()->heap()->InNewSpace(*call_data)) {
460 __ Move(rcx, api_call_info);
461 __ movp(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
462 __ movp(args.GetArgumentOperand(offset - FCA::kDataIndex), rbx);
463 } else { 443 } else {
464 __ Move(args.GetArgumentOperand(offset - FCA::kDataIndex), call_data); 444 MoveHolder(masm, api_receiver, api_holder, rax);
465 } 445 }
466 __ Move(kScratchRegister, 446 GenerateFastApiCallBody(masm,
467 ExternalReference::isolate_address(masm->isolate())); 447 optimization,
468 __ movp(args.GetArgumentOperand(offset - FCA::kIsolateIndex), 448 argc,
469 kScratchRegister); 449 holder,
470 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 450 rbx,
471 __ movp(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex), 451 rcx,
472 kScratchRegister); 452 rdx,
473 __ movp(args.GetArgumentOperand(offset - FCA::kReturnValueOffset), 453 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 } 454 }
482 455
483 456
484 // Generate call to api function. 457 // Generate call to api function.
485 // This function uses push() to generate smaller, faster code than 458 // This function uses push() to generate smaller, faster code than
486 // the version above. It is an optimization that should will be removed 459 // the version above. It is an optimization that should will be removed
487 // when api call ICs are generated in hydrogen. 460 // when api call ICs are generated in hydrogen.
488 static void GenerateFastApiCall(MacroAssembler* masm, 461 static void GenerateFastApiCall(MacroAssembler* masm,
489 const CallOptimization& optimization, 462 const CallOptimization& optimization,
490 Register receiver, 463 Register receiver,
491 Register scratch1, 464 Register scratch1,
492 Register scratch2, 465 Register scratch2,
493 Register scratch3, 466 Register scratch3,
494 int argc, 467 int argc,
495 Register* values) { 468 Register* values) {
496 ASSERT(optimization.is_simple_api_call());
497
498 __ PopReturnAddressTo(scratch1); 469 __ PopReturnAddressTo(scratch1);
499
500 // receiver 470 // receiver
501 __ push(receiver); 471 __ push(receiver);
502
503 // Write the arguments to stack frame. 472 // Write the arguments to stack frame.
504 for (int i = 0; i < argc; i++) { 473 for (int i = 0; i < argc; i++) {
505 Register arg = values[argc-1-i]; 474 Register arg = values[argc-1-i];
506 ASSERT(!receiver.is(arg)); 475 ASSERT(!receiver.is(arg));
507 ASSERT(!scratch1.is(arg)); 476 ASSERT(!scratch1.is(arg));
508 ASSERT(!scratch2.is(arg)); 477 ASSERT(!scratch2.is(arg));
509 ASSERT(!scratch3.is(arg)); 478 ASSERT(!scratch3.is(arg));
510 __ push(arg); 479 __ push(arg);
511 } 480 }
481 __ PushReturnAddressFrom(scratch1);
482 // Stack now matches JSFunction abi.
483 GenerateFastApiCallBody(masm,
484 optimization,
485 argc,
486 receiver,
487 scratch1,
488 scratch2,
489 scratch3,
490 true);
491 }
492
493
494 static void GenerateFastApiCallBody(MacroAssembler* masm,
495 const CallOptimization& optimization,
496 int argc,
497 Register holder,
498 Register scratch1,
499 Register scratch2,
500 Register scratch3,
501 bool restore_context) {
502 // ----------- S t a t e -------------
503 // -- rsp[0] : return address
504 // -- rsp[8] : last argument
505 // -- ...
506 // -- rsp[argc * 8] : first argument
507 // -- rsp[(argc + 1) * 8] : receiver
508 // -----------------------------------
509 ASSERT(optimization.is_simple_api_call());
512 510
513 typedef FunctionCallbackArguments FCA; 511 typedef FunctionCallbackArguments FCA;
514 512
515 STATIC_ASSERT(FCA::kHolderIndex == 0); 513 STATIC_ASSERT(FCA::kHolderIndex == 0);
516 STATIC_ASSERT(FCA::kIsolateIndex == 1); 514 STATIC_ASSERT(FCA::kIsolateIndex == 1);
517 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 515 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
518 STATIC_ASSERT(FCA::kReturnValueOffset == 3); 516 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
519 STATIC_ASSERT(FCA::kDataIndex == 4); 517 STATIC_ASSERT(FCA::kDataIndex == 4);
520 STATIC_ASSERT(FCA::kCalleeIndex == 5); 518 STATIC_ASSERT(FCA::kCalleeIndex == 5);
521 STATIC_ASSERT(FCA::kContextSaveIndex == 6); 519 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
522 STATIC_ASSERT(FCA::kArgsLength == 7); 520 STATIC_ASSERT(FCA::kArgsLength == 7);
523 521
522 __ PopReturnAddressTo(scratch1);
523
524 ASSERT(!holder.is(rsi));
524 // context save 525 // context save
525 __ push(rsi); 526 __ push(rsi);
526 527
527 // Get the function and setup the context. 528 // Get the function and setup the context.
528 Handle<JSFunction> function = optimization.constant_function(); 529 Handle<JSFunction> function = optimization.constant_function();
529 __ Move(scratch2, function); 530 __ Move(scratch2, function);
530 __ push(scratch2); 531 __ push(scratch2);
531 532
532 Isolate* isolate = masm->isolate(); 533 Isolate* isolate = masm->isolate();
533 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 534 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
(...skipping 16 matching lines...) Expand all
550 } 551 }
551 // return value 552 // return value
552 __ push(scratch3); 553 __ push(scratch3);
553 // return value default 554 // return value default
554 __ push(scratch3); 555 __ push(scratch3);
555 // isolate 556 // isolate
556 __ Move(scratch3, 557 __ Move(scratch3,
557 ExternalReference::isolate_address(masm->isolate())); 558 ExternalReference::isolate_address(masm->isolate()));
558 __ push(scratch3); 559 __ push(scratch3);
559 // holder 560 // holder
560 __ push(receiver); 561 __ push(holder);
561 562
562 ASSERT(!scratch1.is(rax)); 563 ASSERT(!scratch1.is(rax));
563 // store receiver address for GenerateFastApiCallBody
564 __ movp(rax, rsp); 564 __ movp(rax, rsp);
565 // Push return address back on stack.
565 __ PushReturnAddressFrom(scratch1); 566 __ PushReturnAddressFrom(scratch1);
566 567
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. 568 // Function address is a foreign pointer outside V8's heap.
591 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 569 Address function_address = v8::ToCData<Address>(api_call_info->callback());
592 570
593 // Allocate the v8::Arguments structure in the arguments' space since 571 // Allocate the v8::Arguments structure in the arguments' space since
594 // it's not controlled by GC. 572 // it's not controlled by GC.
595 const int kApiStackSpace = 4; 573 const int kApiStackSpace = 4;
596 574
597 __ PrepareCallApiFunction(kApiStackSpace); 575 __ PrepareCallApiFunction(kApiStackSpace);
598 576
599 __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_. 577 __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 Register scratch2, 653 Register scratch2,
676 Register scratch3, 654 Register scratch3,
677 Handle<JSObject> interceptor_holder, 655 Handle<JSObject> interceptor_holder,
678 LookupResult* lookup, 656 LookupResult* lookup,
679 Handle<Name> name, 657 Handle<Name> name,
680 const CallOptimization& optimization, 658 const CallOptimization& optimization,
681 Label* miss_label) { 659 Label* miss_label) {
682 ASSERT(optimization.is_constant_call()); 660 ASSERT(optimization.is_constant_call());
683 ASSERT(!lookup->holder()->IsGlobalObject()); 661 ASSERT(!lookup->holder()->IsGlobalObject());
684 662
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(); 663 Counters* counters = masm->isolate()->counters();
701 __ IncrementCounter(counters->call_const_interceptor(), 1); 664 __ IncrementCounter(counters->call_const_interceptor(), 1);
702 665
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 666 // Check that the maps from receiver to interceptor's holder
709 // haven't changed and thus we can invoke interceptor. 667 // haven't changed and thus we can invoke interceptor.
710 Label miss_cleanup; 668 Label miss_cleanup;
711 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
712 Register holder = 669 Register holder =
713 stub_compiler_->CheckPrototypes( 670 stub_compiler_->CheckPrototypes(
714 IC::CurrentTypeOf(object, masm->isolate()), receiver, 671 IC::CurrentTypeOf(object, masm->isolate()), receiver,
715 interceptor_holder, scratch1, scratch2, scratch3, 672 interceptor_holder, scratch1, scratch2, scratch3,
716 name, depth1, miss); 673 name, miss_label);
717 674
718 // Invoke an interceptor and if it provides a value, 675 // Invoke an interceptor and if it provides a value,
719 // branch to |regular_invoke|. 676 // branch to |regular_invoke|.
720 Label regular_invoke; 677 Label regular_invoke;
721 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 678 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
722 &regular_invoke); 679 &regular_invoke);
723 680
724 // Interceptor returned nothing for this property. Try to use cached 681 // Interceptor returned nothing for this property. Try to use cached
725 // constant function. 682 // constant function.
726 683
727 // Check that the maps from interceptor's holder to constant function's 684 // 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. 685 // holder haven't changed and thus we can use cached constant function.
729 if (*interceptor_holder != lookup->holder()) { 686 if (*interceptor_holder != lookup->holder()) {
730 stub_compiler_->CheckPrototypes( 687 stub_compiler_->CheckPrototypes(
731 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, 688 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
732 handle(lookup->holder()), scratch1, scratch2, scratch3, 689 handle(lookup->holder()), scratch1, scratch2, scratch3,
733 name, depth2, miss); 690 name, miss_label);
734 } else { 691 }
735 // CheckPrototypes has a side effect of fetching a 'holder' 692
736 // for API (object which is instanceof for the signature). It's 693 Handle<JSObject> api_receiver;
737 // safe to omit it here, as if present, it should be fetched 694 Handle<JSObject> api_holder;
738 // by the previous CheckPrototypes. 695 if (optimization.is_simple_api_call() &&
739 ASSERT(depth2 == kInvalidProtoDepth); 696 !lookup->holder()->IsGlobalObject()) {
697 api_receiver = object;
698 api_holder = optimization.GetPrototypeOfExpectedType(
699 api_receiver, interceptor_holder);
700 if (api_holder.is_null()) {
701 api_receiver = interceptor_holder;
702 api_holder = optimization.GetPrototypeOfExpectedType(
703 api_receiver, Handle<JSObject>(lookup->holder()));
Toon Verwaest 2014/01/20 19:11:09 This entire code part is a bit weird to me. Why wo
dcarney 2014/01/20 20:23:56 exactly. It's not what you'd expect to call a hol
704 }
740 } 705 }
741 706
742 // Invoke function. 707 // Invoke function.
743 if (can_do_fast_api_call) { 708 if (!api_holder.is_null()) {
744 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 709 int argc = arguments_.immediate();
710 GenerateFastApiCall(masm, optimization, argc, api_receiver, api_holder);
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...) Expand 10 before | Expand all | Expand 10 after
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...) Expand 10 before | Expand all | Expand 10 after
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...) Expand 10 before | Expand all | Expand 10 after
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 Handle<JSObject> api_holder =
1923 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 1865 optimization.GetPrototypeOfExpectedType(receiver, holder);
1866 if (api_holder.is_null()) return Handle<Code>::null();
1924 1867
1925 Label miss, miss_before_stack_reserved; 1868 Label miss;
1926 GenerateNameCheck(name, &miss_before_stack_reserved); 1869 GenerateNameCheck(name, &miss);
1927 1870
1928 const int argc = arguments().immediate(); 1871 const int argc = arguments().immediate();
1929 StackArgumentsAccessor args(rsp, argc); 1872 StackArgumentsAccessor args(rsp, argc);
1930 __ movp(rdx, args.GetReceiverOperand()); 1873 __ movp(rdx, args.GetReceiverOperand());
1931 1874
1932 // Check that the receiver isn't a smi. 1875 // Check that the receiver isn't a smi.
1933 __ JumpIfSmi(rdx, &miss_before_stack_reserved); 1876 __ JumpIfSmi(rdx, &miss);
1934 1877
1935 Counters* counters = isolate()->counters(); 1878 Counters* counters = isolate()->counters();
1936 __ IncrementCounter(counters->call_const(), 1); 1879 __ 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 1880
1943 // Check that the maps haven't changed and find a Holder as a side effect. 1881 // Check that the maps haven't changed and find a Holder as a side effect.
1944 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, 1882 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
1945 rbx, rax, rdi, name, depth, &miss); 1883 rbx, rax, rdi, name, &miss);
1946 1884
1947 // Move the return address on top of the stack. 1885 GenerateFastApiCall(masm(), optimization, argc, receiver, api_holder);
1948 __ movq(rax,
1949 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
1950 __ movq(StackOperandForReturnAddress(0), rax);
1951 1886
1952 GenerateFastApiCall(masm(), optimization, argc); 1887 HandlerFrontendFooter(&miss);
1953
1954 __ bind(&miss);
1955 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1956
1957 HandlerFrontendFooter(&miss_before_stack_reserved);
1958 1888
1959 // Return the generated code. 1889 // Return the generated code.
1960 return GetCode(function); 1890 return GetCode(function);
1961 } 1891 }
1962 1892
1963 1893
1964 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1894 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1965 Label success; 1895 Label success;
1966 // Check that the object is a boolean. 1896 // Check that the object is a boolean.
1967 __ CompareRoot(object, Heap::kTrueValueRootIndex); 1897 __ CompareRoot(object, Heap::kTrueValueRootIndex);
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
2490 // ----------------------------------- 2420 // -----------------------------------
2491 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2421 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2492 } 2422 }
2493 2423
2494 2424
2495 #undef __ 2425 #undef __
2496 2426
2497 } } // namespace v8::internal 2427 } } // namespace v8::internal
2498 2428
2499 #endif // V8_TARGET_ARCH_X64 2429 #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