OLD | NEW |
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 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 #else | 513 #else |
514 Register arguments_arg = rdi; | 514 Register arguments_arg = rdi; |
515 Register callback_arg = rsi; | 515 Register callback_arg = rsi; |
516 #endif | 516 #endif |
517 | 517 |
518 // v8::InvocationCallback's argument. | 518 // v8::InvocationCallback's argument. |
519 __ lea(arguments_arg, StackSpaceOperand(0)); | 519 __ lea(arguments_arg, StackSpaceOperand(0)); |
520 | 520 |
521 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); | 521 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
522 | 522 |
523 Operand context_restore_operand(rbp, | 523 StackArgumentsAccessor args_from_rbp(rbp, kFastApiCallArguments, |
524 (2 + FCA::kContextSaveIndex) * kPointerSize); | 524 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
525 Operand return_value_operand(rbp, | 525 Operand context_restore_operand = args_from_rbp.GetArgumentOperand( |
526 (2 + FCA::kReturnValueOffset) * kPointerSize); | 526 kFastApiCallArguments - 1 - FCA::kContextSaveIndex); |
| 527 Operand return_value_operand = args_from_rbp.GetArgumentOperand( |
| 528 kFastApiCallArguments - 1 - FCA::kReturnValueOffset); |
527 __ CallApiFunctionAndReturn( | 529 __ CallApiFunctionAndReturn( |
528 function_address, | 530 function_address, |
529 thunk_address, | 531 thunk_address, |
530 callback_arg, | 532 callback_arg, |
531 argc + kFastApiCallArguments + 1, | 533 argc + kFastApiCallArguments + 1, |
532 return_value_operand, | 534 return_value_operand, |
533 restore_context ? &context_restore_operand : NULL); | 535 restore_context ? &context_restore_operand : NULL); |
534 } | 536 } |
535 | 537 |
536 | 538 |
537 // Generate call to api function. | 539 // Generate call to api function. |
538 static void GenerateFastApiCall(MacroAssembler* masm, | 540 static void GenerateFastApiCall(MacroAssembler* masm, |
539 const CallOptimization& optimization, | 541 const CallOptimization& optimization, |
540 Register receiver, | 542 Register receiver, |
541 Register scratch, | 543 Register scratch, |
542 int argc, | 544 int argc, |
543 Register* values) { | 545 Register* values) { |
544 ASSERT(optimization.is_simple_api_call()); | 546 ASSERT(optimization.is_simple_api_call()); |
545 ASSERT(!receiver.is(scratch)); | 547 ASSERT(!receiver.is(scratch)); |
546 | 548 |
547 const int stack_space = kFastApiCallArguments + argc + 1; | 549 const int fast_api_call_argc = argc + kFastApiCallArguments; |
548 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; | 550 StackArgumentsAccessor args(rsp, fast_api_call_argc); |
549 // Copy return value. | 551 // argc + 1 is the argument number before FastApiCall arguments, 1 ~ receiver |
550 __ movq(scratch, Operand(rsp, 0)); | 552 const int kHolderIndex = argc + 1 + |
551 // Assign stack space for the call arguments. | 553 kFastApiCallArguments - 1 - FunctionCallbackArguments::kHolderIndex; |
552 __ subq(rsp, Immediate(stack_space * kPointerSize)); | 554 __ movq(scratch, StackOperandForReturnAddress(0)); |
553 // Move the return address on top of the stack. | 555 // Assign stack space for the call arguments and receiver. |
554 __ movq(Operand(rsp, 0), scratch); | 556 __ subq(rsp, Immediate((fast_api_call_argc + 1) * kPointerSize)); |
| 557 __ movq(StackOperandForReturnAddress(0), scratch); |
555 // Write holder to stack frame. | 558 // Write holder to stack frame. |
556 __ movq(Operand(rsp, kHolderIndex * kPointerSize), receiver); | 559 __ movq(args.GetArgumentOperand(kHolderIndex), receiver); |
557 // Write receiver to stack frame. | 560 __ movq(args.GetReceiverOperand(), receiver); |
558 int index = stack_space; | |
559 __ movq(Operand(rsp, index-- * kPointerSize), receiver); | |
560 // Write the arguments to stack frame. | 561 // Write the arguments to stack frame. |
561 for (int i = 0; i < argc; i++) { | 562 for (int i = 0; i < argc; i++) { |
562 ASSERT(!receiver.is(values[i])); | 563 ASSERT(!receiver.is(values[i])); |
563 ASSERT(!scratch.is(values[i])); | 564 ASSERT(!scratch.is(values[i])); |
564 __ movq(Operand(rsp, index-- * kPointerSize), values[i]); | 565 __ movq(args.GetArgumentOperand(i + 1), values[i]); |
565 } | 566 } |
566 | 567 |
567 GenerateFastApiCall(masm, optimization, argc, true); | 568 GenerateFastApiCall(masm, optimization, argc, true); |
568 } | 569 } |
569 | 570 |
570 | 571 |
571 class CallInterceptorCompiler BASE_EMBEDDED { | 572 class CallInterceptorCompiler BASE_EMBEDDED { |
572 public: | 573 public: |
573 CallInterceptorCompiler(StubCompiler* stub_compiler, | 574 CallInterceptorCompiler(StubCompiler* stub_compiler, |
574 const ParameterCount& arguments, | 575 const ParameterCount& arguments, |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1088 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
1088 Register object_reg, | 1089 Register object_reg, |
1089 Handle<JSObject> holder, | 1090 Handle<JSObject> holder, |
1090 Register holder_reg, | 1091 Register holder_reg, |
1091 Register scratch1, | 1092 Register scratch1, |
1092 Register scratch2, | 1093 Register scratch2, |
1093 Handle<Name> name, | 1094 Handle<Name> name, |
1094 int save_at_depth, | 1095 int save_at_depth, |
1095 Label* miss, | 1096 Label* miss, |
1096 PrototypeCheckType check) { | 1097 PrototypeCheckType check) { |
1097 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; | |
1098 // Make sure that the type feedback oracle harvests the receiver map. | 1098 // Make sure that the type feedback oracle harvests the receiver map. |
1099 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1099 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
1100 __ Move(scratch1, Handle<Map>(object->map())); | 1100 __ Move(scratch1, Handle<Map>(object->map())); |
1101 | 1101 |
1102 Handle<JSObject> first = object; | 1102 Handle<JSObject> first = object; |
1103 // Make sure there's no overlap between holder and object registers. | 1103 // Make sure there's no overlap between holder and object registers. |
1104 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1104 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
1105 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1105 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
1106 && !scratch2.is(scratch1)); | 1106 && !scratch2.is(scratch1)); |
1107 | 1107 |
1108 // Keep track of the current object in register reg. On the first | 1108 // Keep track of the current object in register reg. On the first |
1109 // iteration, reg is an alias for object_reg, on later iterations, | 1109 // iteration, reg is an alias for object_reg, on later iterations, |
1110 // it is an alias for holder_reg. | 1110 // it is an alias for holder_reg. |
1111 Register reg = object_reg; | 1111 Register reg = object_reg; |
1112 int depth = 0; | 1112 int depth = 0; |
1113 | 1113 |
| 1114 StackArgumentsAccessor args(rsp, kFastApiCallArguments, |
| 1115 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1116 const int kHolderIndex = kFastApiCallArguments - 1 - |
| 1117 FunctionCallbackArguments::kHolderIndex; |
| 1118 |
1114 if (save_at_depth == depth) { | 1119 if (save_at_depth == depth) { |
1115 __ movq(Operand(rsp, kHolderIndex * kPointerSize), object_reg); | 1120 __ movq(args.GetArgumentOperand(kHolderIndex), object_reg); |
1116 } | 1121 } |
1117 | 1122 |
1118 // Check the maps in the prototype chain. | 1123 // Check the maps in the prototype chain. |
1119 // Traverse the prototype chain from the object and do map checks. | 1124 // Traverse the prototype chain from the object and do map checks. |
1120 Handle<JSObject> current = object; | 1125 Handle<JSObject> current = object; |
1121 while (!current.is_identical_to(holder)) { | 1126 while (!current.is_identical_to(holder)) { |
1122 ++depth; | 1127 ++depth; |
1123 | 1128 |
1124 // Only global objects and objects that do not require access | 1129 // Only global objects and objects that do not require access |
1125 // checks are allowed in stubs. | 1130 // checks are allowed in stubs. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 // 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 |
1166 // in the code. Load it from the map. | 1171 // in the code. Load it from the map. |
1167 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1172 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
1168 } else { | 1173 } else { |
1169 // The prototype is in old space; load it directly. | 1174 // The prototype is in old space; load it directly. |
1170 __ Move(reg, prototype); | 1175 __ Move(reg, prototype); |
1171 } | 1176 } |
1172 } | 1177 } |
1173 | 1178 |
1174 if (save_at_depth == depth) { | 1179 if (save_at_depth == depth) { |
1175 __ movq(Operand(rsp, kHolderIndex * kPointerSize), reg); | 1180 __ movq(args.GetArgumentOperand(kHolderIndex), reg); |
1176 } | 1181 } |
1177 | 1182 |
1178 // Go to the next object in the prototype chain. | 1183 // Go to the next object in the prototype chain. |
1179 current = prototype; | 1184 current = prototype; |
1180 } | 1185 } |
1181 ASSERT(current.is_identical_to(holder)); | 1186 ASSERT(current.is_identical_to(holder)); |
1182 | 1187 |
1183 // Log the check depth. | 1188 // Log the check depth. |
1184 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1189 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
1185 | 1190 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 | 1388 |
1384 // v8::PropertyAccessorInfo::args_. | 1389 // v8::PropertyAccessorInfo::args_. |
1385 __ movq(StackSpaceOperand(0), rax); | 1390 __ movq(StackSpaceOperand(0), rax); |
1386 | 1391 |
1387 // The context register (rsi) has been saved in PrepareCallApiFunction and | 1392 // The context register (rsi) has been saved in PrepareCallApiFunction and |
1388 // could be used to pass arguments. | 1393 // could be used to pass arguments. |
1389 __ lea(accessor_info_arg, StackSpaceOperand(0)); | 1394 __ lea(accessor_info_arg, StackSpaceOperand(0)); |
1390 | 1395 |
1391 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1396 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
1392 | 1397 |
| 1398 // The name handler is counted as an argument. |
| 1399 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); |
| 1400 Operand return_value_operand = args.GetArgumentOperand( |
| 1401 PropertyCallbackArguments::kArgsLength - 1 - |
| 1402 PropertyCallbackArguments::kReturnValueOffset); |
1393 __ CallApiFunctionAndReturn(getter_address, | 1403 __ CallApiFunctionAndReturn(getter_address, |
1394 thunk_address, | 1404 thunk_address, |
1395 getter_arg, | 1405 getter_arg, |
1396 kStackSpace, | 1406 kStackSpace, |
1397 Operand(rbp, 6 * kPointerSize), | 1407 return_value_operand, |
1398 NULL); | 1408 NULL); |
1399 } | 1409 } |
1400 | 1410 |
1401 | 1411 |
1402 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1412 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
1403 // Return the constant value. | 1413 // Return the constant value. |
1404 __ LoadObject(rax, value); | 1414 __ LoadObject(rax, value); |
1405 __ ret(0); | 1415 __ ret(0); |
1406 } | 1416 } |
1407 | 1417 |
(...skipping 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3167 // ----------------------------------- | 3177 // ----------------------------------- |
3168 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3178 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3169 } | 3179 } |
3170 | 3180 |
3171 | 3181 |
3172 #undef __ | 3182 #undef __ |
3173 | 3183 |
3174 } } // namespace v8::internal | 3184 } } // namespace v8::internal |
3175 | 3185 |
3176 #endif // V8_TARGET_ARCH_X64 | 3186 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |