| 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 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 Register name, | 381 Register name, |
| 382 Handle<JSObject> holder_obj, | 382 Handle<JSObject> holder_obj, |
| 383 IC::UtilityId id) { | 383 IC::UtilityId id) { |
| 384 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 384 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 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. | |
| 392 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | |
| 393 | |
| 394 | |
| 395 static void GenerateFastApiCallBody(MacroAssembler* masm, | 391 static void GenerateFastApiCallBody(MacroAssembler* masm, |
| 396 const CallOptimization& optimization, | 392 const CallOptimization& optimization, |
| 397 int argc, | 393 int argc, |
| 398 Register holder, | 394 Register holder_in, |
| 399 Register scratch1, | 395 bool restore_context) { |
| 400 Register scratch2, | 396 ASSERT(optimization.is_simple_api_call()); |
| 401 Register scratch3, | 397 |
| 402 bool restore_context); | 398 // Abi for CallApiFunctionStub. |
| 399 Register callee = rax; |
| 400 Register call_data = rbx; |
| 401 Register holder = rcx; |
| 402 Register api_function_address = rdx; |
| 403 |
| 404 // Put holder in place. |
| 405 __ Move(holder, holder_in); |
| 406 |
| 407 Register scratch = rdi; |
| 408 |
| 409 Isolate* isolate = masm->isolate(); |
| 410 Handle<JSFunction> function = optimization.constant_function(); |
| 411 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 412 Handle<Object> call_data_obj(api_call_info->data(), isolate); |
| 413 |
| 414 // Put callee in place. |
| 415 __ Move(callee, function); |
| 416 |
| 417 bool call_data_undefined = false; |
| 418 // Put call_data in place. |
| 419 if (isolate->heap()->InNewSpace(*call_data_obj)) { |
| 420 __ Move(scratch, api_call_info); |
| 421 __ movp(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset)); |
| 422 } else if (call_data_obj->IsUndefined()) { |
| 423 call_data_undefined = true; |
| 424 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); |
| 425 } else { |
| 426 __ Move(call_data, call_data_obj); |
| 427 } |
| 428 |
| 429 // Put api_function_address in place. |
| 430 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 431 __ Move( |
| 432 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); |
| 433 |
| 434 // Jump to stub. |
| 435 CallApiFunctionStub stub(restore_context, call_data_undefined, argc); |
| 436 __ TailCallStub(&stub); |
| 437 } |
| 403 | 438 |
| 404 | 439 |
| 405 // Generates call to API function. | 440 // Generates call to API function. |
| 406 static void GenerateFastApiCall(MacroAssembler* masm, | 441 static void GenerateFastApiCall(MacroAssembler* masm, |
| 407 const CallOptimization& optimization, | 442 const CallOptimization& optimization, |
| 408 int argc, | 443 int argc, |
| 409 Handle<Map> map_to_holder, | 444 Handle<Map> map_to_holder, |
| 410 CallOptimization::HolderLookup holder_lookup) { | 445 CallOptimization::HolderLookup holder_lookup) { |
| 411 Counters* counters = masm->isolate()->counters(); | 446 Counters* counters = masm->isolate()->counters(); |
| 412 __ IncrementCounter(counters->call_const_fast_api(), 1); | 447 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 432 } | 467 } |
| 433 } | 468 } |
| 434 break; | 469 break; |
| 435 case CallOptimization::kHolderNotFound: | 470 case CallOptimization::kHolderNotFound: |
| 436 UNREACHABLE(); | 471 UNREACHABLE(); |
| 437 } | 472 } |
| 438 GenerateFastApiCallBody(masm, | 473 GenerateFastApiCallBody(masm, |
| 439 optimization, | 474 optimization, |
| 440 argc, | 475 argc, |
| 441 holder_reg, | 476 holder_reg, |
| 442 rbx, | |
| 443 rcx, | |
| 444 rdx, | |
| 445 false); | 477 false); |
| 446 } | 478 } |
| 447 | 479 |
| 448 | 480 |
| 449 // Generate call to api function. | 481 // Generate call to api function. |
| 450 // This function uses push() to generate smaller, faster code than | |
| 451 // the version above. It is an optimization that should will be removed | |
| 452 // when api call ICs are generated in hydrogen. | |
| 453 static void GenerateFastApiCall(MacroAssembler* masm, | 482 static void GenerateFastApiCall(MacroAssembler* masm, |
| 454 const CallOptimization& optimization, | 483 const CallOptimization& optimization, |
| 455 Register receiver, | 484 Register receiver, |
| 456 Register scratch1, | 485 Register scratch1, |
| 457 Register scratch2, | |
| 458 Register scratch3, | |
| 459 int argc, | 486 int argc, |
| 460 Register* values) { | 487 Register* values) { |
| 461 __ PopReturnAddressTo(scratch1); | 488 __ PopReturnAddressTo(scratch1); |
| 462 // receiver | 489 // receiver |
| 463 __ push(receiver); | 490 __ push(receiver); |
| 464 // Write the arguments to stack frame. | 491 // Write the arguments to stack frame. |
| 465 for (int i = 0; i < argc; i++) { | 492 for (int i = 0; i < argc; i++) { |
| 466 Register arg = values[argc-1-i]; | 493 Register arg = values[argc-1-i]; |
| 467 ASSERT(!receiver.is(arg)); | 494 ASSERT(!receiver.is(arg)); |
| 468 ASSERT(!scratch1.is(arg)); | 495 ASSERT(!scratch1.is(arg)); |
| 469 ASSERT(!scratch2.is(arg)); | |
| 470 ASSERT(!scratch3.is(arg)); | |
| 471 __ push(arg); | 496 __ push(arg); |
| 472 } | 497 } |
| 473 __ PushReturnAddressFrom(scratch1); | 498 __ PushReturnAddressFrom(scratch1); |
| 474 // Stack now matches JSFunction abi. | 499 // Stack now matches JSFunction abi. |
| 475 GenerateFastApiCallBody(masm, | 500 GenerateFastApiCallBody(masm, |
| 476 optimization, | 501 optimization, |
| 477 argc, | 502 argc, |
| 478 receiver, | 503 receiver, |
| 479 scratch1, | |
| 480 scratch2, | |
| 481 scratch3, | |
| 482 true); | 504 true); |
| 483 } | 505 } |
| 484 | 506 |
| 485 | 507 |
| 486 static void GenerateFastApiCallBody(MacroAssembler* masm, | |
| 487 const CallOptimization& optimization, | |
| 488 int argc, | |
| 489 Register holder, | |
| 490 Register scratch1, | |
| 491 Register scratch2, | |
| 492 Register scratch3, | |
| 493 bool restore_context) { | |
| 494 // ----------- S t a t e ------------- | |
| 495 // -- rsp[0] : return address | |
| 496 // -- rsp[8] : last argument | |
| 497 // -- ... | |
| 498 // -- rsp[argc * 8] : first argument | |
| 499 // -- rsp[(argc + 1) * 8] : receiver | |
| 500 // ----------------------------------- | |
| 501 ASSERT(optimization.is_simple_api_call()); | |
| 502 | |
| 503 typedef FunctionCallbackArguments FCA; | |
| 504 | |
| 505 STATIC_ASSERT(FCA::kHolderIndex == 0); | |
| 506 STATIC_ASSERT(FCA::kIsolateIndex == 1); | |
| 507 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | |
| 508 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | |
| 509 STATIC_ASSERT(FCA::kDataIndex == 4); | |
| 510 STATIC_ASSERT(FCA::kCalleeIndex == 5); | |
| 511 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | |
| 512 STATIC_ASSERT(FCA::kArgsLength == 7); | |
| 513 | |
| 514 __ PopReturnAddressTo(scratch1); | |
| 515 | |
| 516 ASSERT(!holder.is(rsi)); | |
| 517 // context save | |
| 518 __ push(rsi); | |
| 519 | |
| 520 // Get the function and setup the context. | |
| 521 Handle<JSFunction> function = optimization.constant_function(); | |
| 522 __ Move(scratch2, function); | |
| 523 __ push(scratch2); | |
| 524 __ movp(rsi, FieldOperand(scratch2, JSFunction::kContextOffset)); | |
| 525 | |
| 526 Isolate* isolate = masm->isolate(); | |
| 527 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | |
| 528 Handle<Object> call_data(api_call_info->data(), isolate); | |
| 529 // Push data from ExecutableAccessorInfo. | |
| 530 bool call_data_undefined = false; | |
| 531 if (isolate->heap()->InNewSpace(*call_data)) { | |
| 532 __ Move(scratch2, api_call_info); | |
| 533 __ movp(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset)); | |
| 534 } else if (call_data->IsUndefined()) { | |
| 535 call_data_undefined = true; | |
| 536 __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex); | |
| 537 } else { | |
| 538 __ Move(scratch3, call_data); | |
| 539 } | |
| 540 // call data | |
| 541 __ push(scratch3); | |
| 542 if (!call_data_undefined) { | |
| 543 __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex); | |
| 544 } | |
| 545 // return value | |
| 546 __ push(scratch3); | |
| 547 // return value default | |
| 548 __ push(scratch3); | |
| 549 // isolate | |
| 550 __ Move(scratch3, | |
| 551 ExternalReference::isolate_address(masm->isolate())); | |
| 552 __ push(scratch3); | |
| 553 // holder | |
| 554 __ push(holder); | |
| 555 | |
| 556 ASSERT(!scratch1.is(rax)); | |
| 557 __ movp(rax, rsp); | |
| 558 // Push return address back on stack. | |
| 559 __ PushReturnAddressFrom(scratch1); | |
| 560 | |
| 561 // Function address is a foreign pointer outside V8's heap. | |
| 562 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | |
| 563 | |
| 564 // Allocate the v8::Arguments structure in the arguments' space since | |
| 565 // it's not controlled by GC. | |
| 566 const int kApiStackSpace = 4; | |
| 567 | |
| 568 __ PrepareCallApiFunction(kApiStackSpace); | |
| 569 | |
| 570 __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_. | |
| 571 __ addq(rax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize)); | |
| 572 __ movp(StackSpaceOperand(1), rax); // FunctionCallbackInfo::values_. | |
| 573 __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_. | |
| 574 // FunctionCallbackInfo::is_construct_call_. | |
| 575 __ Set(StackSpaceOperand(3), 0); | |
| 576 | |
| 577 #if defined(__MINGW64__) || defined(_WIN64) | |
| 578 Register arguments_arg = rcx; | |
| 579 Register callback_arg = rdx; | |
| 580 #else | |
| 581 Register arguments_arg = rdi; | |
| 582 Register callback_arg = rsi; | |
| 583 #endif | |
| 584 | |
| 585 // v8::InvocationCallback's argument. | |
| 586 __ lea(arguments_arg, StackSpaceOperand(0)); | |
| 587 | |
| 588 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); | |
| 589 | |
| 590 StackArgumentsAccessor args_from_rbp(rbp, kFastApiCallArguments, | |
| 591 ARGUMENTS_DONT_CONTAIN_RECEIVER); | |
| 592 Operand context_restore_operand = args_from_rbp.GetArgumentOperand( | |
| 593 kFastApiCallArguments - 1 - FCA::kContextSaveIndex); | |
| 594 Operand return_value_operand = args_from_rbp.GetArgumentOperand( | |
| 595 kFastApiCallArguments - 1 - FCA::kReturnValueOffset); | |
| 596 __ CallApiFunctionAndReturn( | |
| 597 function_address, | |
| 598 thunk_address, | |
| 599 callback_arg, | |
| 600 argc + kFastApiCallArguments + 1, | |
| 601 return_value_operand, | |
| 602 restore_context ? &context_restore_operand : NULL); | |
| 603 } | |
| 604 | |
| 605 | |
| 606 class CallInterceptorCompiler BASE_EMBEDDED { | 508 class CallInterceptorCompiler BASE_EMBEDDED { |
| 607 public: | 509 public: |
| 608 CallInterceptorCompiler(CallStubCompiler* stub_compiler, | 510 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 609 const ParameterCount& arguments, | 511 const ParameterCount& arguments, |
| 610 Register name) | 512 Register name) |
| 611 : stub_compiler_(stub_compiler), | 513 : stub_compiler_(stub_compiler), |
| 612 arguments_(arguments), | 514 arguments_(arguments), |
| 613 name_(name) {} | 515 name_(name) {} |
| 614 | 516 |
| 615 void Compile(MacroAssembler* masm, | 517 void Compile(MacroAssembler* masm, |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 representation); | 1174 representation); |
| 1273 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1175 GenerateTailCall(masm(), stub.GetCode(isolate())); |
| 1274 } | 1176 } |
| 1275 } | 1177 } |
| 1276 | 1178 |
| 1277 | 1179 |
| 1278 void LoadStubCompiler::GenerateLoadCallback( | 1180 void LoadStubCompiler::GenerateLoadCallback( |
| 1279 const CallOptimization& call_optimization) { | 1181 const CallOptimization& call_optimization) { |
| 1280 GenerateFastApiCall( | 1182 GenerateFastApiCall( |
| 1281 masm(), call_optimization, receiver(), | 1183 masm(), call_optimization, receiver(), |
| 1282 scratch1(), scratch2(), name(), 0, NULL); | 1184 scratch1(), 0, NULL); |
| 1283 } | 1185 } |
| 1284 | 1186 |
| 1285 | 1187 |
| 1286 void LoadStubCompiler::GenerateLoadCallback( | 1188 void LoadStubCompiler::GenerateLoadCallback( |
| 1287 Register reg, | 1189 Register reg, |
| 1288 Handle<ExecutableAccessorInfo> callback) { | 1190 Handle<ExecutableAccessorInfo> callback) { |
| 1289 // Insert additional parameters into the stack frame above return address. | 1191 // Insert additional parameters into the stack frame above return address. |
| 1290 ASSERT(!scratch4().is(reg)); | 1192 ASSERT(!scratch4().is(reg)); |
| 1291 __ PopReturnAddressTo(scratch4()); | 1193 __ PopReturnAddressTo(scratch4()); |
| 1292 | 1194 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 | 1245 |
| 1344 // v8::PropertyAccessorInfo::args_. | 1246 // v8::PropertyAccessorInfo::args_. |
| 1345 __ movp(StackSpaceOperand(0), rax); | 1247 __ movp(StackSpaceOperand(0), rax); |
| 1346 | 1248 |
| 1347 // The context register (rsi) has been saved in PrepareCallApiFunction and | 1249 // The context register (rsi) has been saved in PrepareCallApiFunction and |
| 1348 // could be used to pass arguments. | 1250 // could be used to pass arguments. |
| 1349 __ lea(accessor_info_arg, StackSpaceOperand(0)); | 1251 __ lea(accessor_info_arg, StackSpaceOperand(0)); |
| 1350 | 1252 |
| 1351 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1253 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
| 1352 | 1254 |
| 1255 Register api_function_address = rdx; |
| 1256 __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE); |
| 1257 |
| 1353 // The name handler is counted as an argument. | 1258 // The name handler is counted as an argument. |
| 1354 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); | 1259 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); |
| 1355 Operand return_value_operand = args.GetArgumentOperand( | 1260 Operand return_value_operand = args.GetArgumentOperand( |
| 1356 PropertyCallbackArguments::kArgsLength - 1 - | 1261 PropertyCallbackArguments::kArgsLength - 1 - |
| 1357 PropertyCallbackArguments::kReturnValueOffset); | 1262 PropertyCallbackArguments::kReturnValueOffset); |
| 1358 __ CallApiFunctionAndReturn(getter_address, | 1263 __ CallApiFunctionAndReturn(api_function_address, |
| 1359 thunk_address, | 1264 thunk_address, |
| 1360 getter_arg, | 1265 getter_arg, |
| 1361 kStackSpace, | 1266 kStackSpace, |
| 1362 return_value_operand, | 1267 return_value_operand, |
| 1363 NULL); | 1268 NULL); |
| 1364 } | 1269 } |
| 1365 | 1270 |
| 1366 | 1271 |
| 1367 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1272 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 1368 // Return the constant value. | 1273 // Return the constant value. |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1785 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1690 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 1786 Handle<JSObject> object, | 1691 Handle<JSObject> object, |
| 1787 Handle<JSObject> holder, | 1692 Handle<JSObject> holder, |
| 1788 Handle<Name> name, | 1693 Handle<Name> name, |
| 1789 const CallOptimization& call_optimization) { | 1694 const CallOptimization& call_optimization) { |
| 1790 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), | 1695 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 1791 receiver(), holder, name); | 1696 receiver(), holder, name); |
| 1792 | 1697 |
| 1793 Register values[] = { value() }; | 1698 Register values[] = { value() }; |
| 1794 GenerateFastApiCall( | 1699 GenerateFastApiCall( |
| 1795 masm(), call_optimization, receiver(), scratch1(), | 1700 masm(), call_optimization, receiver(), |
| 1796 scratch2(), this->name(), 1, values); | 1701 scratch1(), 1, values); |
| 1797 | 1702 |
| 1798 // Return the generated code. | 1703 // Return the generated code. |
| 1799 return GetCode(kind(), Code::FAST, name); | 1704 return GetCode(kind(), Code::FAST, name); |
| 1800 } | 1705 } |
| 1801 | 1706 |
| 1802 | 1707 |
| 1803 #undef __ | 1708 #undef __ |
| 1804 #define __ ACCESS_MASM(masm) | 1709 #define __ ACCESS_MASM(masm) |
| 1805 | 1710 |
| 1806 | 1711 |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2112 // ----------------------------------- | 2017 // ----------------------------------- |
| 2113 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2018 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 2114 } | 2019 } |
| 2115 | 2020 |
| 2116 | 2021 |
| 2117 #undef __ | 2022 #undef __ |
| 2118 | 2023 |
| 2119 } } // namespace v8::internal | 2024 } } // namespace v8::internal |
| 2120 | 2025 |
| 2121 #endif // V8_TARGET_ARCH_X64 | 2026 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |