| 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 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 bool restore_context) { |
| 448 // ----------- S t a t e ------------- | 448 // ----------- S t a t e ------------- |
| 449 // -- rsp[0] : return address | 449 // -- rsp[0] : return address |
| 450 // -- rsp[8] - rsp[58] : FunctionCallbackInfo, incl. | 450 // -- rsp[8] - rsp[56] : FunctionCallbackInfo, incl. |
| 451 // : object passing the type check | 451 // : object passing the type check |
| 452 // (set by CheckPrototypes) | 452 // (set by CheckPrototypes) |
| 453 // -- rsp[64] : last argument | 453 // -- rsp[64] : last argument |
| 454 // -- ... | 454 // -- ... |
| 455 // -- rsp[(argc + 7) * 8] : first argument | 455 // -- rsp[(argc + 7) * 8] : first argument |
| 456 // -- rsp[(argc + 8) * 8] : receiver | 456 // -- rsp[(argc + 8) * 8] : receiver |
| 457 // ----------------------------------- | 457 // ----------------------------------- |
| 458 typedef FunctionCallbackArguments FCA; | 458 typedef FunctionCallbackArguments FCA; |
| 459 StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments); | 459 StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments); |
| 460 | 460 |
| 461 // Save calling context. | 461 // Save calling context. |
| 462 __ movq(args.GetArgumentOperand(argc + 1 - FCA::kContextSaveIndex), rsi); | 462 int offset = argc + kFastApiCallArguments; |
| 463 __ movq(args.GetArgumentOperand(offset - FCA::kContextSaveIndex), rsi); |
| 463 | 464 |
| 464 // Get the function and setup the context. | 465 // Get the function and setup the context. |
| 465 Handle<JSFunction> function = optimization.constant_function(); | 466 Handle<JSFunction> function = optimization.constant_function(); |
| 466 __ LoadHeapObject(rdi, function); | 467 __ LoadHeapObject(rdi, function); |
| 467 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 468 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 468 // Construct the FunctionCallbackInfo on the stack. | 469 // Construct the FunctionCallbackInfo on the stack. |
| 469 __ movq(args.GetArgumentOperand(argc + 1 - FCA::kCalleeIndex), rdi); | 470 __ movq(args.GetArgumentOperand(offset - FCA::kCalleeIndex), rdi); |
| 470 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 471 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 471 Handle<Object> call_data(api_call_info->data(), masm->isolate()); | 472 Handle<Object> call_data(api_call_info->data(), masm->isolate()); |
| 472 if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 473 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
| 473 __ Move(rcx, api_call_info); | 474 __ Move(rcx, api_call_info); |
| 474 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); | 475 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); |
| 475 __ movq(args.GetArgumentOperand(argc + 1 - FCA::kDataIndex), rbx); | 476 __ movq(args.GetArgumentOperand(offset - FCA::kDataIndex), rbx); |
| 476 } else { | 477 } else { |
| 477 __ Move(args.GetArgumentOperand(argc + 1 - FCA::kDataIndex), call_data); | 478 __ Move(args.GetArgumentOperand(offset - FCA::kDataIndex), call_data); |
| 478 } | 479 } |
| 479 __ movq(kScratchRegister, | 480 __ movq(kScratchRegister, |
| 480 ExternalReference::isolate_address(masm->isolate())); | 481 ExternalReference::isolate_address(masm->isolate())); |
| 481 __ movq(args.GetArgumentOperand(argc + 1 - FCA::kIsolateIndex), | 482 __ movq(args.GetArgumentOperand(offset - FCA::kIsolateIndex), |
| 482 kScratchRegister); | 483 kScratchRegister); |
| 483 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 484 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); |
| 484 __ movq( | 485 __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex), |
| 485 args.GetArgumentOperand(argc + 1 - FCA::kReturnValueDefaultValueIndex), | 486 kScratchRegister); |
| 486 kScratchRegister); | 487 __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueOffset), |
| 487 __ movq(args.GetArgumentOperand(argc + 1 - FCA::kReturnValueOffset), | |
| 488 kScratchRegister); | 488 kScratchRegister); |
| 489 | 489 |
| 490 // Prepare arguments. | 490 // Prepare arguments. |
| 491 STATIC_ASSERT(kFastApiCallArguments == 7); | 491 STATIC_ASSERT(kFastApiCallArguments == 7); |
| 492 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); | 492 __ lea(rbx, Operand(rsp, 1 * kPointerSize)); |
| 493 | 493 |
| 494 // Function address is a foreign pointer outside V8's heap. | 494 // Function address is a foreign pointer outside V8's heap. |
| 495 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 495 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 496 | 496 |
| 497 // Allocate the v8::Arguments structure in the arguments' space since | 497 // Allocate the v8::Arguments structure in the arguments' space since |
| 498 // it's not controlled by GC. | 498 // it's not controlled by GC. |
| 499 const int kApiStackSpace = 4; | 499 const int kApiStackSpace = 4; |
| 500 | 500 |
| 501 __ PrepareCallApiFunction(kApiStackSpace); | 501 __ PrepareCallApiFunction(kApiStackSpace); |
| 502 | 502 |
| 503 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. | 503 __ movq(StackSpaceOperand(0), rbx); // FunctionCallbackInfo::implicit_args_. |
| 504 __ addq(rbx, Immediate(argc * kPointerSize)); | 504 __ addq(rbx, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize)); |
| 505 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. | 505 __ movq(StackSpaceOperand(1), rbx); // FunctionCallbackInfo::values_. |
| 506 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. | 506 __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_. |
| 507 // v8::Arguments::is_construct_call_. | 507 // FunctionCallbackInfo::is_construct_call_. |
| 508 __ Set(StackSpaceOperand(3), 0); | 508 __ Set(StackSpaceOperand(3), 0); |
| 509 | 509 |
| 510 #if defined(__MINGW64__) || defined(_WIN64) | 510 #if defined(__MINGW64__) || defined(_WIN64) |
| 511 Register arguments_arg = rcx; | 511 Register arguments_arg = rcx; |
| 512 Register callback_arg = rdx; | 512 Register callback_arg = rdx; |
| 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( | 523 StackArgumentsAccessor args_from_rbp(rbp, kFastApiCallArguments, |
| 524 rbp, (kFastApiCallArguments + 1 + FCA::kContextSaveIndex) * kPointerSize); | 524 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 525 Operand return_value_operand( | 525 Operand context_restore_operand = args_from_rbp.GetArgumentOperand( |
| 526 rbp, | 526 kFastApiCallArguments - 1 - FCA::kContextSaveIndex); |
| 527 (kFastApiCallArguments + 1 + FCA::kReturnValueOffset) * kPointerSize); | 527 Operand return_value_operand = args_from_rbp.GetArgumentOperand( |
| 528 kFastApiCallArguments - 1 - FCA::kReturnValueOffset); |
| 528 __ CallApiFunctionAndReturn( | 529 __ CallApiFunctionAndReturn( |
| 529 function_address, | 530 function_address, |
| 530 thunk_address, | 531 thunk_address, |
| 531 callback_arg, | 532 callback_arg, |
| 532 argc + kFastApiCallArguments + 1, | 533 argc + kFastApiCallArguments + 1, |
| 533 return_value_operand, | 534 return_value_operand, |
| 534 restore_context ? &context_restore_operand : NULL); | 535 restore_context ? &context_restore_operand : NULL); |
| 535 } | 536 } |
| 536 | 537 |
| 537 | 538 |
| 538 // Generate call to api function. | 539 // Generate call to api function. |
| 539 static void GenerateFastApiCall(MacroAssembler* masm, | 540 static void GenerateFastApiCall(MacroAssembler* masm, |
| 540 const CallOptimization& optimization, | 541 const CallOptimization& optimization, |
| 541 Register receiver, | 542 Register receiver, |
| 542 Register scratch, | 543 Register scratch, |
| 543 int argc, | 544 int argc, |
| 544 Register* values) { | 545 Register* values) { |
| 545 ASSERT(optimization.is_simple_api_call()); | 546 ASSERT(optimization.is_simple_api_call()); |
| 546 ASSERT(!receiver.is(scratch)); | 547 ASSERT(!receiver.is(scratch)); |
| 547 | 548 |
| 548 const int stack_space = kFastApiCallArguments + argc + 1; | 549 const int fast_api_call_argc = argc + kFastApiCallArguments; |
| 549 const int kHolderIndex = kFastApiCallArguments + | 550 StackArgumentsAccessor args(rsp, fast_api_call_argc); |
| 550 FunctionCallbackArguments::kHolderIndex; | 551 // argc + 1 is the argument number before FastApiCall arguments, 1 ~ receiver |
| 551 // Copy return value. | 552 const int kHolderIndex = argc + 1 + |
| 552 __ movq(scratch, Operand(rsp, 0)); | 553 kFastApiCallArguments - 1 - FunctionCallbackArguments::kHolderIndex; |
| 553 // Assign stack space for the call arguments. | 554 __ movq(scratch, StackOperandForReturnAddress(0)); |
| 554 __ subq(rsp, Immediate(stack_space * kPointerSize)); | 555 // Assign stack space for the call arguments and receiver. |
| 555 // Move the return address on top of the stack. | 556 __ subq(rsp, Immediate((fast_api_call_argc + 1) * kPointerSize)); |
| 556 __ movq(Operand(rsp, 0), scratch); | 557 __ movq(StackOperandForReturnAddress(0), scratch); |
| 557 // Write holder to stack frame. | 558 // Write holder to stack frame. |
| 558 __ movq(Operand(rsp, kHolderIndex * kPointerSize), receiver); | 559 __ movq(args.GetArgumentOperand(kHolderIndex), receiver); |
| 559 // Write receiver to stack frame. | 560 __ movq(args.GetReceiverOperand(), receiver); |
| 560 int index = stack_space; | |
| 561 __ movq(Operand(rsp, index-- * kPointerSize), receiver); | |
| 562 // Write the arguments to stack frame. | 561 // Write the arguments to stack frame. |
| 563 for (int i = 0; i < argc; i++) { | 562 for (int i = 0; i < argc; i++) { |
| 564 ASSERT(!receiver.is(values[i])); | 563 ASSERT(!receiver.is(values[i])); |
| 565 ASSERT(!scratch.is(values[i])); | 564 ASSERT(!scratch.is(values[i])); |
| 566 __ movq(Operand(rsp, index-- * kPointerSize), values[i]); | 565 __ movq(args.GetArgumentOperand(i + 1), values[i]); |
| 567 } | 566 } |
| 568 | 567 |
| 569 GenerateFastApiCall(masm, optimization, argc, true); | 568 GenerateFastApiCall(masm, optimization, argc, true); |
| 570 } | 569 } |
| 571 | 570 |
| 572 | 571 |
| 573 class CallInterceptorCompiler BASE_EMBEDDED { | 572 class CallInterceptorCompiler BASE_EMBEDDED { |
| 574 public: | 573 public: |
| 575 CallInterceptorCompiler(StubCompiler* stub_compiler, | 574 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 576 const ParameterCount& arguments, | 575 const ParameterCount& arguments, |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1088 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 1090 Register object_reg, | 1089 Register object_reg, |
| 1091 Handle<JSObject> holder, | 1090 Handle<JSObject> holder, |
| 1092 Register holder_reg, | 1091 Register holder_reg, |
| 1093 Register scratch1, | 1092 Register scratch1, |
| 1094 Register scratch2, | 1093 Register scratch2, |
| 1095 Handle<Name> name, | 1094 Handle<Name> name, |
| 1096 int save_at_depth, | 1095 int save_at_depth, |
| 1097 Label* miss, | 1096 Label* miss, |
| 1098 PrototypeCheckType check) { | 1097 PrototypeCheckType check) { |
| 1099 const int kHolderIndex = kFastApiCallArguments + | |
| 1100 FunctionCallbackArguments::kHolderIndex; | |
| 1101 // Make sure that the type feedback oracle harvests the receiver map. | 1098 // Make sure that the type feedback oracle harvests the receiver map. |
| 1102 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1099 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1103 __ Move(scratch1, Handle<Map>(object->map())); | 1100 __ Move(scratch1, Handle<Map>(object->map())); |
| 1104 | 1101 |
| 1105 Handle<JSObject> first = object; | 1102 Handle<JSObject> first = object; |
| 1106 // Make sure there's no overlap between holder and object registers. | 1103 // Make sure there's no overlap between holder and object registers. |
| 1107 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1104 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1108 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1105 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1109 && !scratch2.is(scratch1)); | 1106 && !scratch2.is(scratch1)); |
| 1110 | 1107 |
| 1111 // 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 |
| 1112 // iteration, reg is an alias for object_reg, on later iterations, | 1109 // iteration, reg is an alias for object_reg, on later iterations, |
| 1113 // it is an alias for holder_reg. | 1110 // it is an alias for holder_reg. |
| 1114 Register reg = object_reg; | 1111 Register reg = object_reg; |
| 1115 int depth = 0; | 1112 int depth = 0; |
| 1116 | 1113 |
| 1114 StackArgumentsAccessor args(rsp, kFastApiCallArguments, |
| 1115 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1116 const int kHolderIndex = kFastApiCallArguments - 1 - |
| 1117 FunctionCallbackArguments::kHolderIndex; |
| 1118 |
| 1117 if (save_at_depth == depth) { | 1119 if (save_at_depth == depth) { |
| 1118 __ movq(Operand(rsp, kHolderIndex * kPointerSize), object_reg); | 1120 __ movq(args.GetArgumentOperand(kHolderIndex), object_reg); |
| 1119 } | 1121 } |
| 1120 | 1122 |
| 1121 // Check the maps in the prototype chain. | 1123 // Check the maps in the prototype chain. |
| 1122 // Traverse the prototype chain from the object and do map checks. | 1124 // Traverse the prototype chain from the object and do map checks. |
| 1123 Handle<JSObject> current = object; | 1125 Handle<JSObject> current = object; |
| 1124 while (!current.is_identical_to(holder)) { | 1126 while (!current.is_identical_to(holder)) { |
| 1125 ++depth; | 1127 ++depth; |
| 1126 | 1128 |
| 1127 // Only global objects and objects that do not require access | 1129 // Only global objects and objects that do not require access |
| 1128 // checks are allowed in stubs. | 1130 // checks are allowed in stubs. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 // 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 |
| 1169 // in the code. Load it from the map. | 1171 // in the code. Load it from the map. |
| 1170 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1172 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1171 } else { | 1173 } else { |
| 1172 // The prototype is in old space; load it directly. | 1174 // The prototype is in old space; load it directly. |
| 1173 __ Move(reg, prototype); | 1175 __ Move(reg, prototype); |
| 1174 } | 1176 } |
| 1175 } | 1177 } |
| 1176 | 1178 |
| 1177 if (save_at_depth == depth) { | 1179 if (save_at_depth == depth) { |
| 1178 __ movq(Operand(rsp, kHolderIndex * kPointerSize), reg); | 1180 __ movq(args.GetArgumentOperand(kHolderIndex), reg); |
| 1179 } | 1181 } |
| 1180 | 1182 |
| 1181 // Go to the next object in the prototype chain. | 1183 // Go to the next object in the prototype chain. |
| 1182 current = prototype; | 1184 current = prototype; |
| 1183 } | 1185 } |
| 1184 ASSERT(current.is_identical_to(holder)); | 1186 ASSERT(current.is_identical_to(holder)); |
| 1185 | 1187 |
| 1186 // Log the check depth. | 1188 // Log the check depth. |
| 1187 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1189 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1188 | 1190 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1326 } | 1328 } |
| 1327 | 1329 |
| 1328 | 1330 |
| 1329 void BaseLoadStubCompiler::GenerateLoadCallback( | 1331 void BaseLoadStubCompiler::GenerateLoadCallback( |
| 1330 Register reg, | 1332 Register reg, |
| 1331 Handle<ExecutableAccessorInfo> callback) { | 1333 Handle<ExecutableAccessorInfo> callback) { |
| 1332 // Insert additional parameters into the stack frame above return address. | 1334 // Insert additional parameters into the stack frame above return address. |
| 1333 ASSERT(!scratch4().is(reg)); | 1335 ASSERT(!scratch4().is(reg)); |
| 1334 __ PopReturnAddressTo(scratch4()); | 1336 __ PopReturnAddressTo(scratch4()); |
| 1335 | 1337 |
| 1336 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 0); | 1338 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
| 1337 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == -1); | 1339 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
| 1338 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == -2); | 1340 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
| 1339 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == -3); | 1341 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
| 1340 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == -4); | 1342 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
| 1341 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == -5); | 1343 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
| 1344 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); |
| 1342 __ push(receiver()); // receiver | 1345 __ push(receiver()); // receiver |
| 1343 if (heap()->InNewSpace(callback->data())) { | 1346 if (heap()->InNewSpace(callback->data())) { |
| 1344 ASSERT(!scratch2().is(reg)); | 1347 ASSERT(!scratch2().is(reg)); |
| 1345 __ Move(scratch2(), callback); | 1348 __ Move(scratch2(), callback); |
| 1346 __ push(FieldOperand(scratch2(), | 1349 __ push(FieldOperand(scratch2(), |
| 1347 ExecutableAccessorInfo::kDataOffset)); // data | 1350 ExecutableAccessorInfo::kDataOffset)); // data |
| 1348 } else { | 1351 } else { |
| 1349 __ Push(Handle<Object>(callback->data(), isolate())); | 1352 __ Push(Handle<Object>(callback->data(), isolate())); |
| 1350 } | 1353 } |
| 1351 ASSERT(!kScratchRegister.is(reg)); | 1354 ASSERT(!kScratchRegister.is(reg)); |
| 1352 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 1355 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); |
| 1353 __ push(kScratchRegister); // return value | 1356 __ push(kScratchRegister); // return value |
| 1354 __ push(kScratchRegister); // return value default | 1357 __ push(kScratchRegister); // return value default |
| 1355 __ PushAddress(ExternalReference::isolate_address(isolate())); | 1358 __ PushAddress(ExternalReference::isolate_address(isolate())); |
| 1356 __ push(reg); // holder | 1359 __ push(reg); // holder |
| 1357 __ push(name()); // name | 1360 __ push(name()); // name |
| 1358 // Save a pointer to where we pushed the arguments pointer. This will be | 1361 // Save a pointer to where we pushed the arguments pointer. This will be |
| 1359 // passed as the const ExecutableAccessorInfo& to the C++ callback. | 1362 // passed as the const PropertyAccessorInfo& to the C++ callback. |
| 1360 | 1363 |
| 1361 Address getter_address = v8::ToCData<Address>(callback->getter()); | 1364 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 1362 | 1365 |
| 1363 #if defined(__MINGW64__) || defined(_WIN64) | 1366 #if defined(__MINGW64__) || defined(_WIN64) |
| 1364 Register getter_arg = r8; | 1367 Register getter_arg = r8; |
| 1365 Register accessor_info_arg = rdx; | 1368 Register accessor_info_arg = rdx; |
| 1366 Register name_arg = rcx; | 1369 Register name_arg = rcx; |
| 1367 #else | 1370 #else |
| 1368 Register getter_arg = rdx; | 1371 Register getter_arg = rdx; |
| 1369 Register accessor_info_arg = rsi; | 1372 Register accessor_info_arg = rsi; |
| 1370 Register name_arg = rdi; | 1373 Register name_arg = rdi; |
| 1371 #endif | 1374 #endif |
| 1372 | 1375 |
| 1373 ASSERT(!name_arg.is(scratch4())); | 1376 ASSERT(!name_arg.is(scratch4())); |
| 1374 __ movq(name_arg, rsp); | 1377 __ movq(name_arg, rsp); |
| 1375 __ PushReturnAddressFrom(scratch4()); | 1378 __ PushReturnAddressFrom(scratch4()); |
| 1376 | 1379 |
| 1377 // v8::Arguments::values_ and handler for name. | 1380 // v8::Arguments::values_ and handler for name. |
| 1378 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; | 1381 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; |
| 1379 | 1382 |
| 1380 // Allocate v8::AccessorInfo in non-GCed stack space. | 1383 // Allocate v8::AccessorInfo in non-GCed stack space. |
| 1381 const int kArgStackSpace = 1; | 1384 const int kArgStackSpace = 1; |
| 1382 | 1385 |
| 1383 __ PrepareCallApiFunction(kArgStackSpace); | 1386 __ PrepareCallApiFunction(kArgStackSpace); |
| 1384 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); | 1387 __ lea(rax, Operand(name_arg, 1 * kPointerSize)); |
| 1385 __ lea(rax, Operand(name_arg, 6 * kPointerSize)); | |
| 1386 | 1388 |
| 1387 // v8::AccessorInfo::args_. | 1389 // v8::PropertyAccessorInfo::args_. |
| 1388 __ movq(StackSpaceOperand(0), rax); | 1390 __ movq(StackSpaceOperand(0), rax); |
| 1389 | 1391 |
| 1390 // The context register (rsi) has been saved in PrepareCallApiFunction and | 1392 // The context register (rsi) has been saved in PrepareCallApiFunction and |
| 1391 // could be used to pass arguments. | 1393 // could be used to pass arguments. |
| 1392 __ lea(accessor_info_arg, StackSpaceOperand(0)); | 1394 __ lea(accessor_info_arg, StackSpaceOperand(0)); |
| 1393 | 1395 |
| 1394 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1396 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
| 1395 | 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); |
| 1396 __ CallApiFunctionAndReturn(getter_address, | 1403 __ CallApiFunctionAndReturn(getter_address, |
| 1397 thunk_address, | 1404 thunk_address, |
| 1398 getter_arg, | 1405 getter_arg, |
| 1399 kStackSpace, | 1406 kStackSpace, |
| 1400 Operand(rbp, 6 * kPointerSize), | 1407 return_value_operand, |
| 1401 NULL); | 1408 NULL); |
| 1402 } | 1409 } |
| 1403 | 1410 |
| 1404 | 1411 |
| 1405 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1412 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 1406 // Return the constant value. | 1413 // Return the constant value. |
| 1407 __ LoadObject(rax, value); | 1414 __ LoadObject(rax, value); |
| 1408 __ ret(0); | 1415 __ ret(0); |
| 1409 } | 1416 } |
| 1410 | 1417 |
| (...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2184 // If the object is not a JSObject or we got an unexpected number of | 2191 // If the object is not a JSObject or we got an unexpected number of |
| 2185 // arguments, bail out to the regular call. | 2192 // arguments, bail out to the regular call. |
| 2186 const int argc = arguments().immediate(); | 2193 const int argc = arguments().immediate(); |
| 2187 StackArgumentsAccessor args(rsp, argc); | 2194 StackArgumentsAccessor args(rsp, argc); |
| 2188 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2195 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2189 | 2196 |
| 2190 Label miss; | 2197 Label miss; |
| 2191 GenerateNameCheck(name, &miss); | 2198 GenerateNameCheck(name, &miss); |
| 2192 | 2199 |
| 2193 if (cell.is_null()) { | 2200 if (cell.is_null()) { |
| 2194 __ movq(rdx, args.GetArgumentOperand(argc - 1)); | 2201 __ movq(rdx, args.GetReceiverOperand()); |
| 2195 __ JumpIfSmi(rdx, &miss); | 2202 __ JumpIfSmi(rdx, &miss); |
| 2196 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2203 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2197 name, &miss); | 2204 name, &miss); |
| 2198 } else { | 2205 } else { |
| 2199 ASSERT(cell->value() == *function); | 2206 ASSERT(cell->value() == *function); |
| 2200 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2207 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2201 &miss); | 2208 &miss); |
| 2202 GenerateLoadFunctionFromCell(cell, function, &miss); | 2209 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2203 } | 2210 } |
| 2204 | 2211 |
| 2205 // Load the char code argument. | 2212 // Load the char code argument. |
| 2206 Register code = rbx; | 2213 Register code = rbx; |
| 2207 __ movq(code, args.GetArgumentOperand(argc)); | 2214 __ movq(code, args.GetArgumentOperand(1)); |
| 2208 | 2215 |
| 2209 // Check the code is a smi. | 2216 // Check the code is a smi. |
| 2210 Label slow; | 2217 Label slow; |
| 2211 __ JumpIfNotSmi(code, &slow); | 2218 __ JumpIfNotSmi(code, &slow); |
| 2212 | 2219 |
| 2213 // Convert the smi code to uint16. | 2220 // Convert the smi code to uint16. |
| 2214 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); | 2221 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); |
| 2215 | 2222 |
| 2216 StringCharFromCodeGenerator generator(code, rax); | 2223 StringCharFromCodeGenerator generator(code, rax); |
| 2217 generator.GenerateFast(masm()); | 2224 generator.GenerateFast(masm()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2247 Handle<String> name, | 2254 Handle<String> name, |
| 2248 Code::StubType type) { | 2255 Code::StubType type) { |
| 2249 // ----------- S t a t e ------------- | 2256 // ----------- S t a t e ------------- |
| 2250 // -- rcx : name | 2257 // -- rcx : name |
| 2251 // -- rsp[0] : return address | 2258 // -- rsp[0] : return address |
| 2252 // -- rsp[(argc - n) * 4] : arg[n] (zero-based) | 2259 // -- rsp[(argc - n) * 4] : arg[n] (zero-based) |
| 2253 // -- ... | 2260 // -- ... |
| 2254 // -- rsp[(argc + 1) * 4] : receiver | 2261 // -- rsp[(argc + 1) * 4] : receiver |
| 2255 // ----------------------------------- | 2262 // ----------------------------------- |
| 2256 const int argc = arguments().immediate(); | 2263 const int argc = arguments().immediate(); |
| 2264 StackArgumentsAccessor args(rsp, argc); |
| 2257 | 2265 |
| 2258 // If the object is not a JSObject or we got an unexpected number of | 2266 // If the object is not a JSObject or we got an unexpected number of |
| 2259 // arguments, bail out to the regular call. | 2267 // arguments, bail out to the regular call. |
| 2260 if (!object->IsJSObject() || argc != 1) { | 2268 if (!object->IsJSObject() || argc != 1) { |
| 2261 return Handle<Code>::null(); | 2269 return Handle<Code>::null(); |
| 2262 } | 2270 } |
| 2263 | 2271 |
| 2264 Label miss; | 2272 Label miss; |
| 2265 GenerateNameCheck(name, &miss); | 2273 GenerateNameCheck(name, &miss); |
| 2266 | 2274 |
| 2267 if (cell.is_null()) { | 2275 if (cell.is_null()) { |
| 2268 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2276 __ movq(rdx, args.GetReceiverOperand()); |
| 2269 | 2277 |
| 2270 STATIC_ASSERT(kSmiTag == 0); | 2278 STATIC_ASSERT(kSmiTag == 0); |
| 2271 __ JumpIfSmi(rdx, &miss); | 2279 __ JumpIfSmi(rdx, &miss); |
| 2272 | 2280 |
| 2273 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2281 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2274 name, &miss); | 2282 name, &miss); |
| 2275 } else { | 2283 } else { |
| 2276 ASSERT(cell->value() == *function); | 2284 ASSERT(cell->value() == *function); |
| 2277 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2285 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2278 &miss); | 2286 &miss); |
| 2279 GenerateLoadFunctionFromCell(cell, function, &miss); | 2287 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2280 } | 2288 } |
| 2281 | 2289 |
| 2282 // Load the (only) argument into rax. | 2290 // Load the (only) argument into rax. |
| 2283 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 2291 __ movq(rax, args.GetArgumentOperand(1)); |
| 2284 | 2292 |
| 2285 // Check if the argument is a smi. | 2293 // Check if the argument is a smi. |
| 2286 Label smi; | 2294 Label smi; |
| 2287 STATIC_ASSERT(kSmiTag == 0); | 2295 STATIC_ASSERT(kSmiTag == 0); |
| 2288 __ JumpIfSmi(rax, &smi); | 2296 __ JumpIfSmi(rax, &smi); |
| 2289 | 2297 |
| 2290 // Check if the argument is a heap number and load its value into xmm0. | 2298 // Check if the argument is a heap number and load its value into xmm0. |
| 2291 Label slow; | 2299 Label slow; |
| 2292 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); | 2300 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); |
| 2293 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); | 2301 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2340 __ andpd(xmm1, xmm2); | 2348 __ andpd(xmm1, xmm2); |
| 2341 __ subsd(xmm0, xmm1); | 2349 __ subsd(xmm0, xmm1); |
| 2342 | 2350 |
| 2343 // Return a new heap number. | 2351 // Return a new heap number. |
| 2344 __ AllocateHeapNumber(rax, rbx, &slow); | 2352 __ AllocateHeapNumber(rax, rbx, &slow); |
| 2345 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); | 2353 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
| 2346 __ ret(2 * kPointerSize); | 2354 __ ret(2 * kPointerSize); |
| 2347 | 2355 |
| 2348 // Return the argument (when it's an already round heap number). | 2356 // Return the argument (when it's an already round heap number). |
| 2349 __ bind(&already_round); | 2357 __ bind(&already_round); |
| 2350 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 2358 __ movq(rax, args.GetArgumentOperand(1)); |
| 2351 __ ret(2 * kPointerSize); | 2359 __ ret(2 * kPointerSize); |
| 2352 | 2360 |
| 2353 // Tail call the full function. We do not have to patch the receiver | 2361 // Tail call the full function. We do not have to patch the receiver |
| 2354 // because the function makes no use of it. | 2362 // because the function makes no use of it. |
| 2355 __ bind(&slow); | 2363 __ bind(&slow); |
| 2356 ParameterCount expected(function); | 2364 ParameterCount expected(function); |
| 2357 __ InvokeFunction(function, expected, arguments(), | 2365 __ InvokeFunction(function, expected, arguments(), |
| 2358 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2366 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2359 | 2367 |
| 2360 __ bind(&miss); | 2368 __ bind(&miss); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2384 // If the object is not a JSObject or we got an unexpected number of | 2392 // If the object is not a JSObject or we got an unexpected number of |
| 2385 // arguments, bail out to the regular call. | 2393 // arguments, bail out to the regular call. |
| 2386 const int argc = arguments().immediate(); | 2394 const int argc = arguments().immediate(); |
| 2387 StackArgumentsAccessor args(rsp, argc); | 2395 StackArgumentsAccessor args(rsp, argc); |
| 2388 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2396 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2389 | 2397 |
| 2390 Label miss; | 2398 Label miss; |
| 2391 GenerateNameCheck(name, &miss); | 2399 GenerateNameCheck(name, &miss); |
| 2392 | 2400 |
| 2393 if (cell.is_null()) { | 2401 if (cell.is_null()) { |
| 2394 __ movq(rdx, args.GetArgumentOperand(argc - 1)); | 2402 __ movq(rdx, args.GetReceiverOperand()); |
| 2395 __ JumpIfSmi(rdx, &miss); | 2403 __ JumpIfSmi(rdx, &miss); |
| 2396 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2404 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2397 name, &miss); | 2405 name, &miss); |
| 2398 } else { | 2406 } else { |
| 2399 ASSERT(cell->value() == *function); | 2407 ASSERT(cell->value() == *function); |
| 2400 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2408 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2401 &miss); | 2409 &miss); |
| 2402 GenerateLoadFunctionFromCell(cell, function, &miss); | 2410 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2403 } | 2411 } |
| 2404 // Load the (only) argument into rax. | 2412 // Load the (only) argument into rax. |
| 2405 __ movq(rax, args.GetArgumentOperand(argc)); | 2413 __ movq(rax, args.GetArgumentOperand(1)); |
| 2406 | 2414 |
| 2407 // Check if the argument is a smi. | 2415 // Check if the argument is a smi. |
| 2408 Label not_smi; | 2416 Label not_smi; |
| 2409 STATIC_ASSERT(kSmiTag == 0); | 2417 STATIC_ASSERT(kSmiTag == 0); |
| 2410 __ JumpIfNotSmi(rax, ¬_smi); | 2418 __ JumpIfNotSmi(rax, ¬_smi); |
| 2411 | 2419 |
| 2412 // Branchless abs implementation, refer to below: | 2420 // Branchless abs implementation, refer to below: |
| 2413 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs | 2421 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs |
| 2414 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 | 2422 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 |
| 2415 // otherwise. | 2423 // otherwise. |
| (...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3170 // ----------------------------------- | 3178 // ----------------------------------- |
| 3171 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3179 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3172 } | 3180 } |
| 3173 | 3181 |
| 3174 | 3182 |
| 3175 #undef __ | 3183 #undef __ |
| 3176 | 3184 |
| 3177 } } // namespace v8::internal | 3185 } } // namespace v8::internal |
| 3178 | 3186 |
| 3179 #endif // V8_TARGET_ARCH_X64 | 3187 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |