| 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 |