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 |