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 23903053: reland 16744: add context save for GenerateFastApiCall (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 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/x64/macro-assembler-x64.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 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 __ movq(scratch, StackOperandForReturnAddress(0)); 436 __ movq(scratch, StackOperandForReturnAddress(0));
437 __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize), 437 __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize),
438 scratch); 438 scratch);
439 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); 439 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
440 } 440 }
441 441
442 442
443 // Generates call to API function. 443 // Generates call to API function.
444 static void GenerateFastApiCall(MacroAssembler* masm, 444 static void GenerateFastApiCall(MacroAssembler* masm,
445 const CallOptimization& optimization, 445 const CallOptimization& optimization,
446 int argc) { 446 int argc,
447 bool restore_context) {
447 // ----------- S t a t e ------------- 448 // ----------- S t a t e -------------
448 // -- rsp[0] : return address 449 // -- rsp[0] : return address
449 // -- rsp[8] : object passing the type check 450 // -- rsp[8] : context save
451 // -- rsp[16] : object passing the type check
450 // (last fast api call extra argument, 452 // (last fast api call extra argument,
451 // set by CheckPrototypes) 453 // set by CheckPrototypes)
452 // -- rsp[16] : api function 454 // -- rsp[24] : api function
453 // (first fast api call extra argument) 455 // (first fast api call extra argument)
454 // -- rsp[24] : api call data 456 // -- rsp[32] : api call data
455 // -- rsp[32] : isolate 457 // -- rsp[40] : isolate
456 // -- rsp[40] : ReturnValue default value 458 // -- rsp[48] : ReturnValue default value
457 // -- rsp[48] : ReturnValue 459 // -- rsp[56] : ReturnValue
458 // 460 //
459 // -- rsp[56] : last argument 461 // -- rsp[64] : last argument
460 // -- ... 462 // -- ...
461 // -- rsp[(argc + 6) * 8] : first argument 463 // -- rsp[(argc + 7) * 8] : first argument
462 // -- rsp[(argc + 7) * 8] : receiver 464 // -- rsp[(argc + 8) * 8] : receiver
463 // ----------------------------------- 465 // -----------------------------------
466 int api_call_argc = argc + kFastApiCallArguments;
467 StackArgumentsAccessor args(rsp, api_call_argc);
468
469 // Save calling context.
470 __ movq(args.GetArgumentOperand(api_call_argc), rsi);
471
464 // Get the function and setup the context. 472 // Get the function and setup the context.
465 Handle<JSFunction> function = optimization.constant_function(); 473 Handle<JSFunction> function = optimization.constant_function();
466 __ LoadHeapObject(rdi, function); 474 __ LoadHeapObject(rdi, function);
467 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 475 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
468
469 int api_call_argc = argc + kFastApiCallArguments;
470 StackArgumentsAccessor args(rsp, api_call_argc);
471
472 // Pass the additional arguments. 476 // Pass the additional arguments.
473 __ movq(args.GetArgumentOperand(api_call_argc - 1), rdi); 477 __ movq(args.GetArgumentOperand(api_call_argc - 2), rdi);
474 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 478 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
475 Handle<Object> call_data(api_call_info->data(), masm->isolate()); 479 Handle<Object> call_data(api_call_info->data(), masm->isolate());
476 if (masm->isolate()->heap()->InNewSpace(*call_data)) { 480 if (masm->isolate()->heap()->InNewSpace(*call_data)) {
477 __ Move(rcx, api_call_info); 481 __ Move(rcx, api_call_info);
478 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); 482 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
479 __ movq(args.GetArgumentOperand(api_call_argc - 2), rbx); 483 __ movq(args.GetArgumentOperand(api_call_argc - 3), rbx);
480 } else { 484 } else {
481 __ Move(args.GetArgumentOperand(api_call_argc - 2), call_data); 485 __ Move(args.GetArgumentOperand(api_call_argc - 3), call_data);
482 } 486 }
483 __ movq(kScratchRegister, 487 __ movq(kScratchRegister,
484 ExternalReference::isolate_address(masm->isolate())); 488 ExternalReference::isolate_address(masm->isolate()));
485 __ movq(args.GetArgumentOperand(api_call_argc - 3), kScratchRegister); 489 __ movq(args.GetArgumentOperand(api_call_argc - 4), kScratchRegister);
486 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 490 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
487 __ movq(args.GetArgumentOperand(api_call_argc - 4), kScratchRegister);
488 __ movq(args.GetArgumentOperand(api_call_argc - 5), kScratchRegister); 491 __ movq(args.GetArgumentOperand(api_call_argc - 5), kScratchRegister);
492 __ movq(args.GetArgumentOperand(api_call_argc - 6), kScratchRegister);
489 493
490 // Prepare arguments. 494 // Prepare arguments.
491 STATIC_ASSERT(kFastApiCallArguments == 6); 495 STATIC_ASSERT(kFastApiCallArguments == 7);
492 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); 496 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize));
493 497
494 // Function address is a foreign pointer outside V8's heap. 498 // Function address is a foreign pointer outside V8's heap.
495 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 499 Address function_address = v8::ToCData<Address>(api_call_info->callback());
496 500
497 #if defined(__MINGW64__) || defined(_WIN64)
498 Register arguments_arg = rcx;
499 Register callback_arg = rdx;
500 #else
501 Register arguments_arg = rdi;
502 Register callback_arg = rsi;
503 #endif
504
505 // Allocate the v8::Arguments structure in the arguments' space since 501 // Allocate the v8::Arguments structure in the arguments' space since
506 // it's not controlled by GC. 502 // it's not controlled by GC.
507 const int kApiStackSpace = 4; 503 const int kApiStackSpace = 4;
508 504
509 __ PrepareCallApiFunction(kApiStackSpace); 505 __ PrepareCallApiFunction(kApiStackSpace);
510 506
511 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. 507 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_.
512 __ addq(rbx, Immediate(argc * kPointerSize)); 508 __ addq(rbx, Immediate(argc * kPointerSize));
513 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. 509 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_.
514 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. 510 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_.
515 // v8::Arguments::is_construct_call_. 511 // v8::Arguments::is_construct_call_.
516 __ Set(StackSpaceOperand(3), 0); 512 __ Set(StackSpaceOperand(3), 0);
517 513
514 #if defined(__MINGW64__) || defined(_WIN64)
515 Register arguments_arg = rcx;
516 Register callback_arg = rdx;
517 #else
518 Register arguments_arg = rdi;
519 Register callback_arg = rsi;
520 #endif
521
518 // v8::InvocationCallback's argument. 522 // v8::InvocationCallback's argument.
519 __ lea(arguments_arg, StackSpaceOperand(0)); 523 __ lea(arguments_arg, StackSpaceOperand(0));
520 524
521 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); 525 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
522 526
527 Operand context_restore_operand(rbp, 2 * kPointerSize);
528 Operand return_value_operand(
529 rbp, (kFastApiCallArguments + 1) * kPointerSize);
523 __ CallApiFunctionAndReturn(function_address, 530 __ CallApiFunctionAndReturn(function_address,
524 thunk_address, 531 thunk_address,
525 callback_arg, 532 callback_arg,
526 api_call_argc + 1, 533 api_call_argc + 1,
527 kFastApiCallArguments + 1); 534 return_value_operand,
535 restore_context ?
536 &context_restore_operand : NULL);
528 } 537 }
529 538
530 539
531 // Generate call to api function. 540 // Generate call to api function.
532 static void GenerateFastApiCall(MacroAssembler* masm, 541 static void GenerateFastApiCall(MacroAssembler* masm,
533 const CallOptimization& optimization, 542 const CallOptimization& optimization,
534 Register receiver, 543 Register receiver,
535 Register scratch, 544 Register scratch,
536 int argc, 545 int argc,
537 Register* values) { 546 Register* values) {
538 ASSERT(optimization.is_simple_api_call()); 547 ASSERT(optimization.is_simple_api_call());
539 ASSERT(!receiver.is(scratch)); 548 ASSERT(!receiver.is(scratch));
540 549
541 const int stack_space = kFastApiCallArguments + argc + 1; 550 const int stack_space = kFastApiCallArguments + argc + 1;
551 const int kHolderIndex = kFastApiCallArguments +
552 FunctionCallbackArguments::kHolderIndex;
542 // Copy return value. 553 // Copy return value.
543 __ movq(scratch, Operand(rsp, 0)); 554 __ movq(scratch, Operand(rsp, 0));
544 // Assign stack space for the call arguments. 555 // Assign stack space for the call arguments.
545 __ subq(rsp, Immediate(stack_space * kPointerSize)); 556 __ subq(rsp, Immediate(stack_space * kPointerSize));
546 // Move the return address on top of the stack. 557 // Move the return address on top of the stack.
547 __ movq(Operand(rsp, 0), scratch); 558 __ movq(Operand(rsp, 0), scratch);
548 // Write holder to stack frame. 559 // Write holder to stack frame.
549 __ movq(Operand(rsp, 1 * kPointerSize), receiver); 560 __ movq(Operand(rsp, kHolderIndex * kPointerSize), receiver);
550 // Write receiver to stack frame. 561 // Write receiver to stack frame.
551 int index = stack_space; 562 int index = stack_space;
552 __ movq(Operand(rsp, index-- * kPointerSize), receiver); 563 __ movq(Operand(rsp, index-- * kPointerSize), receiver);
553 // Write the arguments to stack frame. 564 // Write the arguments to stack frame.
554 for (int i = 0; i < argc; i++) { 565 for (int i = 0; i < argc; i++) {
555 ASSERT(!receiver.is(values[i])); 566 ASSERT(!receiver.is(values[i]));
556 ASSERT(!scratch.is(values[i])); 567 ASSERT(!scratch.is(values[i]));
557 __ movq(Operand(rsp, index-- * kPointerSize), values[i]); 568 __ movq(Operand(rsp, index-- * kPointerSize), values[i]);
558 } 569 }
559 570
560 GenerateFastApiCall(masm, optimization, argc); 571 GenerateFastApiCall(masm, optimization, argc, true);
561 } 572 }
562 573
563 574
564 class CallInterceptorCompiler BASE_EMBEDDED { 575 class CallInterceptorCompiler BASE_EMBEDDED {
565 public: 576 public:
566 CallInterceptorCompiler(StubCompiler* stub_compiler, 577 CallInterceptorCompiler(StubCompiler* stub_compiler,
567 const ParameterCount& arguments, 578 const ParameterCount& arguments,
568 Register name, 579 Register name,
569 Code::ExtraICState extra_ic_state) 580 Code::ExtraICState extra_ic_state)
570 : stub_compiler_(stub_compiler), 581 : stub_compiler_(stub_compiler),
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 } else { 675 } else {
665 // CheckPrototypes has a side effect of fetching a 'holder' 676 // CheckPrototypes has a side effect of fetching a 'holder'
666 // for API (object which is instanceof for the signature). It's 677 // for API (object which is instanceof for the signature). It's
667 // safe to omit it here, as if present, it should be fetched 678 // safe to omit it here, as if present, it should be fetched
668 // by the previous CheckPrototypes. 679 // by the previous CheckPrototypes.
669 ASSERT(depth2 == kInvalidProtoDepth); 680 ASSERT(depth2 == kInvalidProtoDepth);
670 } 681 }
671 682
672 // Invoke function. 683 // Invoke function.
673 if (can_do_fast_api_call) { 684 if (can_do_fast_api_call) {
674 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 685 GenerateFastApiCall(masm, optimization, arguments_.immediate(), false);
675 } else { 686 } else {
676 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) 687 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
677 ? CALL_AS_FUNCTION 688 ? CALL_AS_FUNCTION
678 : CALL_AS_METHOD; 689 : CALL_AS_METHOD;
679 Handle<JSFunction> fun = optimization.constant_function(); 690 Handle<JSFunction> fun = optimization.constant_function();
680 ParameterCount expected(fun); 691 ParameterCount expected(fun);
681 __ InvokeFunction(fun, expected, arguments_, 692 __ InvokeFunction(fun, expected, arguments_,
682 JUMP_FUNCTION, NullCallWrapper(), call_kind); 693 JUMP_FUNCTION, NullCallWrapper(), call_kind);
683 } 694 }
684 695
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
1080 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, 1091 Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
1081 Register object_reg, 1092 Register object_reg,
1082 Handle<JSObject> holder, 1093 Handle<JSObject> holder,
1083 Register holder_reg, 1094 Register holder_reg,
1084 Register scratch1, 1095 Register scratch1,
1085 Register scratch2, 1096 Register scratch2,
1086 Handle<Name> name, 1097 Handle<Name> name,
1087 int save_at_depth, 1098 int save_at_depth,
1088 Label* miss, 1099 Label* miss,
1089 PrototypeCheckType check) { 1100 PrototypeCheckType check) {
1101 const int kHolderIndex = kFastApiCallArguments +
1102 FunctionCallbackArguments::kHolderIndex;
1090 // Make sure that the type feedback oracle harvests the receiver map. 1103 // Make sure that the type feedback oracle harvests the receiver map.
1091 // TODO(svenpanne) Remove this hack when all ICs are reworked. 1104 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1092 __ Move(scratch1, Handle<Map>(object->map())); 1105 __ Move(scratch1, Handle<Map>(object->map()));
1093 1106
1094 Handle<JSObject> first = object; 1107 Handle<JSObject> first = object;
1095 // Make sure there's no overlap between holder and object registers. 1108 // Make sure there's no overlap between holder and object registers.
1096 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 1109 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1097 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1110 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1098 && !scratch2.is(scratch1)); 1111 && !scratch2.is(scratch1));
1099 1112
1100 // Keep track of the current object in register reg. On the first 1113 // Keep track of the current object in register reg. On the first
1101 // iteration, reg is an alias for object_reg, on later iterations, 1114 // iteration, reg is an alias for object_reg, on later iterations,
1102 // it is an alias for holder_reg. 1115 // it is an alias for holder_reg.
1103 Register reg = object_reg; 1116 Register reg = object_reg;
1104 int depth = 0; 1117 int depth = 0;
1105 1118
1106 if (save_at_depth == depth) { 1119 if (save_at_depth == depth) {
1107 __ movq(Operand(rsp, kPCOnStackSize), object_reg); 1120 __ movq(Operand(rsp, kHolderIndex * kPointerSize), object_reg);
1108 } 1121 }
1109 1122
1110 // Check the maps in the prototype chain. 1123 // Check the maps in the prototype chain.
1111 // Traverse the prototype chain from the object and do map checks. 1124 // Traverse the prototype chain from the object and do map checks.
1112 Handle<JSObject> current = object; 1125 Handle<JSObject> current = object;
1113 while (!current.is_identical_to(holder)) { 1126 while (!current.is_identical_to(holder)) {
1114 ++depth; 1127 ++depth;
1115 1128
1116 // Only global objects and objects that do not require access 1129 // Only global objects and objects that do not require access
1117 // checks are allowed in stubs. 1130 // checks are allowed in stubs.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 // The prototype is in new space; we cannot store a reference to it 1170 // The prototype is in new space; we cannot store a reference to it
1158 // in the code. Load it from the map. 1171 // in the code. Load it from the map.
1159 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1172 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1160 } else { 1173 } else {
1161 // The prototype is in old space; load it directly. 1174 // The prototype is in old space; load it directly.
1162 __ Move(reg, prototype); 1175 __ Move(reg, prototype);
1163 } 1176 }
1164 } 1177 }
1165 1178
1166 if (save_at_depth == depth) { 1179 if (save_at_depth == depth) {
1167 __ movq(Operand(rsp, kPCOnStackSize), reg); 1180 __ movq(Operand(rsp, kHolderIndex * kPointerSize), reg);
1168 } 1181 }
1169 1182
1170 // Go to the next object in the prototype chain. 1183 // Go to the next object in the prototype chain.
1171 current = prototype; 1184 current = prototype;
1172 } 1185 }
1173 ASSERT(current.is_identical_to(holder)); 1186 ASSERT(current.is_identical_to(holder));
1174 1187
1175 // Log the check depth. 1188 // Log the check depth.
1176 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1189 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1177 1190
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 // The context register (rsi) has been saved in PrepareCallApiFunction and 1392 // The context register (rsi) has been saved in PrepareCallApiFunction and
1380 // could be used to pass arguments. 1393 // could be used to pass arguments.
1381 __ lea(accessor_info_arg, StackSpaceOperand(0)); 1394 __ lea(accessor_info_arg, StackSpaceOperand(0));
1382 1395
1383 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); 1396 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1384 1397
1385 __ CallApiFunctionAndReturn(getter_address, 1398 __ CallApiFunctionAndReturn(getter_address,
1386 thunk_address, 1399 thunk_address,
1387 getter_arg, 1400 getter_arg,
1388 kStackSpace, 1401 kStackSpace,
1389 6); 1402 Operand(rbp, 6 * kPointerSize),
1403 NULL);
1390 } 1404 }
1391 1405
1392 1406
1393 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { 1407 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
1394 // Return the constant value. 1408 // Return the constant value.
1395 __ LoadObject(rax, value); 1409 __ LoadObject(rax, value);
1396 __ ret(0); 1410 __ ret(0);
1397 } 1411 }
1398 1412
1399 1413
(...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after
2497 2511
2498 // Check that the maps haven't changed and find a Holder as a side effect. 2512 // Check that the maps haven't changed and find a Holder as a side effect.
2499 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 2513 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
2500 name, depth, &miss); 2514 name, depth, &miss);
2501 2515
2502 // Move the return address on top of the stack. 2516 // Move the return address on top of the stack.
2503 __ movq(rax, 2517 __ movq(rax,
2504 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); 2518 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
2505 __ movq(StackOperandForReturnAddress(0), rax); 2519 __ movq(StackOperandForReturnAddress(0), rax);
2506 2520
2507 GenerateFastApiCall(masm(), optimization, argc); 2521 GenerateFastApiCall(masm(), optimization, argc, false);
2508 2522
2509 __ bind(&miss); 2523 __ bind(&miss);
2510 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 2524 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
2511 2525
2512 __ bind(&miss_before_stack_reserved); 2526 __ bind(&miss_before_stack_reserved);
2513 GenerateMissBranch(); 2527 GenerateMissBranch();
2514 2528
2515 // Return the generated code. 2529 // Return the generated code.
2516 return GetCode(function); 2530 return GetCode(function);
2517 } 2531 }
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
3158 // ----------------------------------- 3172 // -----------------------------------
3159 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); 3173 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
3160 } 3174 }
3161 3175
3162 3176
3163 #undef __ 3177 #undef __
3164 3178
3165 } } // namespace v8::internal 3179 } } // namespace v8::internal
3166 3180
3167 #endif // V8_TARGET_ARCH_X64 3181 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698