| 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 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 Register name, | 385 Register name, |
| 386 Handle<JSObject> holder_obj, | 386 Handle<JSObject> holder_obj, |
| 387 IC::UtilityId id) { | 387 IC::UtilityId id) { |
| 388 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 388 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 389 __ CallExternalReference( | 389 __ CallExternalReference( |
| 390 ExternalReference(IC_Utility(id), masm->isolate()), | 390 ExternalReference(IC_Utility(id), masm->isolate()), |
| 391 StubCache::kInterceptorArgsLength); | 391 StubCache::kInterceptorArgsLength); |
| 392 } | 392 } |
| 393 | 393 |
| 394 | 394 |
| 395 static void GenerateFastApiCallBody(MacroAssembler* masm, | 395 // Generate call to api function. |
| 396 const CallOptimization& optimization, | 396 static void GenerateFastApiCall(MacroAssembler* masm, |
| 397 int argc, | 397 const CallOptimization& optimization, |
| 398 Register holder_in, | 398 Handle<Map> receiver_map, |
| 399 bool restore_context) { | 399 Register receiver, |
| 400 Register scratch_in, |
| 401 int argc, |
| 402 Register* values) { |
| 400 ASSERT(optimization.is_simple_api_call()); | 403 ASSERT(optimization.is_simple_api_call()); |
| 401 | 404 |
| 405 __ PopReturnAddressTo(scratch_in); |
| 406 // receiver |
| 407 __ push(receiver); |
| 408 // Write the arguments to stack frame. |
| 409 for (int i = 0; i < argc; i++) { |
| 410 Register arg = values[argc-1-i]; |
| 411 ASSERT(!receiver.is(arg)); |
| 412 ASSERT(!scratch_in.is(arg)); |
| 413 __ push(arg); |
| 414 } |
| 415 __ PushReturnAddressFrom(scratch_in); |
| 416 // Stack now matches JSFunction abi. |
| 417 |
| 402 // Abi for CallApiFunctionStub. | 418 // Abi for CallApiFunctionStub. |
| 403 Register callee = rax; | 419 Register callee = rax; |
| 404 Register call_data = rbx; | 420 Register call_data = rbx; |
| 405 Register holder = rcx; | 421 Register holder = rcx; |
| 406 Register api_function_address = rdx; | 422 Register api_function_address = rdx; |
| 423 Register scratch = rdi; // scratch_in is no longer valid. |
| 407 | 424 |
| 408 // Put holder in place. | 425 // Put holder in place. |
| 409 __ Move(holder, holder_in); | 426 CallOptimization::HolderLookup holder_lookup; |
| 410 | 427 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |
| 411 Register scratch = rdi; | 428 receiver_map, |
| 429 &holder_lookup); |
| 430 switch (holder_lookup) { |
| 431 case CallOptimization::kHolderIsReceiver: |
| 432 __ Move(holder, receiver); |
| 433 break; |
| 434 case CallOptimization::kHolderFound: |
| 435 __ Move(holder, api_holder); |
| 436 break; |
| 437 case CallOptimization::kHolderNotFound: |
| 438 UNREACHABLE(); |
| 439 break; |
| 440 } |
| 412 | 441 |
| 413 Isolate* isolate = masm->isolate(); | 442 Isolate* isolate = masm->isolate(); |
| 414 Handle<JSFunction> function = optimization.constant_function(); | 443 Handle<JSFunction> function = optimization.constant_function(); |
| 415 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 444 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 416 Handle<Object> call_data_obj(api_call_info->data(), isolate); | 445 Handle<Object> call_data_obj(api_call_info->data(), isolate); |
| 417 | 446 |
| 418 // Put callee in place. | 447 // Put callee in place. |
| 419 __ Move(callee, function); | 448 __ Move(callee, function); |
| 420 | 449 |
| 421 bool call_data_undefined = false; | 450 bool call_data_undefined = false; |
| 422 // Put call_data in place. | 451 // Put call_data in place. |
| 423 if (isolate->heap()->InNewSpace(*call_data_obj)) { | 452 if (isolate->heap()->InNewSpace(*call_data_obj)) { |
| 424 __ Move(scratch, api_call_info); | 453 __ Move(scratch, api_call_info); |
| 425 __ movp(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset)); | 454 __ movp(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset)); |
| 426 } else if (call_data_obj->IsUndefined()) { | 455 } else if (call_data_obj->IsUndefined()) { |
| 427 call_data_undefined = true; | 456 call_data_undefined = true; |
| 428 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); | 457 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); |
| 429 } else { | 458 } else { |
| 430 __ Move(call_data, call_data_obj); | 459 __ Move(call_data, call_data_obj); |
| 431 } | 460 } |
| 432 | 461 |
| 433 // Put api_function_address in place. | 462 // Put api_function_address in place. |
| 434 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 463 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 435 __ Move( | 464 __ Move( |
| 436 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); | 465 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); |
| 437 | 466 |
| 438 // Jump to stub. | 467 // Jump to stub. |
| 439 CallApiFunctionStub stub(restore_context, call_data_undefined, argc); | 468 CallApiFunctionStub stub(true, call_data_undefined, argc); |
| 440 __ TailCallStub(&stub); | 469 __ TailCallStub(&stub); |
| 441 } | 470 } |
| 442 | 471 |
| 443 | 472 |
| 444 // Generate call to api function. | |
| 445 static void GenerateFastApiCall(MacroAssembler* masm, | |
| 446 const CallOptimization& optimization, | |
| 447 Register receiver, | |
| 448 Register scratch1, | |
| 449 int argc, | |
| 450 Register* values) { | |
| 451 __ PopReturnAddressTo(scratch1); | |
| 452 // receiver | |
| 453 __ push(receiver); | |
| 454 // Write the arguments to stack frame. | |
| 455 for (int i = 0; i < argc; i++) { | |
| 456 Register arg = values[argc-1-i]; | |
| 457 ASSERT(!receiver.is(arg)); | |
| 458 ASSERT(!scratch1.is(arg)); | |
| 459 __ push(arg); | |
| 460 } | |
| 461 __ PushReturnAddressFrom(scratch1); | |
| 462 // Stack now matches JSFunction abi. | |
| 463 GenerateFastApiCallBody(masm, | |
| 464 optimization, | |
| 465 argc, | |
| 466 receiver, | |
| 467 true); | |
| 468 } | |
| 469 | |
| 470 | |
| 471 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 473 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 472 Label* label, | 474 Label* label, |
| 473 Handle<Name> name) { | 475 Handle<Name> name) { |
| 474 if (!label->is_unused()) { | 476 if (!label->is_unused()) { |
| 475 __ bind(label); | 477 __ bind(label); |
| 476 __ Move(this->name(), name); | 478 __ Move(this->name(), name); |
| 477 } | 479 } |
| 478 } | 480 } |
| 479 | 481 |
| 480 | 482 |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 } else { | 963 } else { |
| 962 KeyedLoadFieldStub stub(field.is_inobject(holder), | 964 KeyedLoadFieldStub stub(field.is_inobject(holder), |
| 963 field.translate(holder), | 965 field.translate(holder), |
| 964 representation); | 966 representation); |
| 965 GenerateTailCall(masm(), stub.GetCode(isolate())); | 967 GenerateTailCall(masm(), stub.GetCode(isolate())); |
| 966 } | 968 } |
| 967 } | 969 } |
| 968 | 970 |
| 969 | 971 |
| 970 void LoadStubCompiler::GenerateLoadCallback( | 972 void LoadStubCompiler::GenerateLoadCallback( |
| 971 const CallOptimization& call_optimization) { | 973 const CallOptimization& call_optimization, |
| 974 Handle<Map> receiver_map) { |
| 972 GenerateFastApiCall( | 975 GenerateFastApiCall( |
| 973 masm(), call_optimization, receiver(), | 976 masm(), call_optimization, receiver_map, |
| 974 scratch1(), 0, NULL); | 977 receiver(), scratch1(), 0, NULL); |
| 975 } | 978 } |
| 976 | 979 |
| 977 | 980 |
| 978 void LoadStubCompiler::GenerateLoadCallback( | 981 void LoadStubCompiler::GenerateLoadCallback( |
| 979 Register reg, | 982 Register reg, |
| 980 Handle<ExecutableAccessorInfo> callback) { | 983 Handle<ExecutableAccessorInfo> callback) { |
| 981 // Insert additional parameters into the stack frame above return address. | 984 // Insert additional parameters into the stack frame above return address. |
| 982 ASSERT(!scratch4().is(reg)); | 985 ASSERT(!scratch4().is(reg)); |
| 983 __ PopReturnAddressTo(scratch4()); | 986 __ PopReturnAddressTo(scratch4()); |
| 984 | 987 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1161 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 1159 Handle<JSObject> object, | 1162 Handle<JSObject> object, |
| 1160 Handle<JSObject> holder, | 1163 Handle<JSObject> holder, |
| 1161 Handle<Name> name, | 1164 Handle<Name> name, |
| 1162 const CallOptimization& call_optimization) { | 1165 const CallOptimization& call_optimization) { |
| 1163 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), | 1166 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 1164 receiver(), holder, name); | 1167 receiver(), holder, name); |
| 1165 | 1168 |
| 1166 Register values[] = { value() }; | 1169 Register values[] = { value() }; |
| 1167 GenerateFastApiCall( | 1170 GenerateFastApiCall( |
| 1168 masm(), call_optimization, receiver(), | 1171 masm(), call_optimization, handle(object->map()), |
| 1169 scratch1(), 1, values); | 1172 receiver(), scratch1(), 1, values); |
| 1170 | 1173 |
| 1171 // Return the generated code. | 1174 // Return the generated code. |
| 1172 return GetCode(kind(), Code::FAST, name); | 1175 return GetCode(kind(), Code::FAST, name); |
| 1173 } | 1176 } |
| 1174 | 1177 |
| 1175 | 1178 |
| 1176 #undef __ | 1179 #undef __ |
| 1177 #define __ ACCESS_MASM(masm) | 1180 #define __ ACCESS_MASM(masm) |
| 1178 | 1181 |
| 1179 | 1182 |
| 1180 void StoreStubCompiler::GenerateStoreViaSetter( | 1183 void StoreStubCompiler::GenerateStoreViaSetter( |
| 1181 MacroAssembler* masm, | 1184 MacroAssembler* masm, |
| 1185 Handle<HeapType> type, |
| 1182 Handle<JSFunction> setter) { | 1186 Handle<JSFunction> setter) { |
| 1183 // ----------- S t a t e ------------- | 1187 // ----------- S t a t e ------------- |
| 1184 // -- rax : value | 1188 // -- rax : value |
| 1185 // -- rcx : name | 1189 // -- rcx : name |
| 1186 // -- rdx : receiver | 1190 // -- rdx : receiver |
| 1187 // -- rsp[0] : return address | 1191 // -- rsp[0] : return address |
| 1188 // ----------------------------------- | 1192 // ----------------------------------- |
| 1189 { | 1193 { |
| 1190 FrameScope scope(masm, StackFrame::INTERNAL); | 1194 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1195 Register receiver = rdx; |
| 1196 Register value = rax; |
| 1191 | 1197 |
| 1192 // Save value register, so we can restore it later. | 1198 // Save value register, so we can restore it later. |
| 1193 __ push(rax); | 1199 __ push(value); |
| 1194 | 1200 |
| 1195 if (!setter.is_null()) { | 1201 if (!setter.is_null()) { |
| 1196 // Call the JavaScript setter with receiver and value on the stack. | 1202 // Call the JavaScript setter with receiver and value on the stack. |
| 1197 __ push(rdx); | 1203 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 1198 __ push(rax); | 1204 // Swap in the global receiver. |
| 1205 __ movp(receiver, |
| 1206 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); |
| 1207 } |
| 1208 __ push(receiver); |
| 1209 __ push(value); |
| 1199 ParameterCount actual(1); | 1210 ParameterCount actual(1); |
| 1200 ParameterCount expected(setter); | 1211 ParameterCount expected(setter); |
| 1201 __ InvokeFunction(setter, expected, actual, | 1212 __ InvokeFunction(setter, expected, actual, |
| 1202 CALL_FUNCTION, NullCallWrapper()); | 1213 CALL_FUNCTION, NullCallWrapper()); |
| 1203 } else { | 1214 } else { |
| 1204 // If we generate a global code snippet for deoptimization only, remember | 1215 // If we generate a global code snippet for deoptimization only, remember |
| 1205 // the place to continue after deoptimization. | 1216 // the place to continue after deoptimization. |
| 1206 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); | 1217 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); |
| 1207 } | 1218 } |
| 1208 | 1219 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1315 static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 }; | 1326 static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 }; |
| 1316 return registers; | 1327 return registers; |
| 1317 } | 1328 } |
| 1318 | 1329 |
| 1319 | 1330 |
| 1320 #undef __ | 1331 #undef __ |
| 1321 #define __ ACCESS_MASM(masm) | 1332 #define __ ACCESS_MASM(masm) |
| 1322 | 1333 |
| 1323 | 1334 |
| 1324 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1335 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
| 1336 Handle<HeapType> type, |
| 1325 Register receiver, | 1337 Register receiver, |
| 1326 Handle<JSFunction> getter) { | 1338 Handle<JSFunction> getter) { |
| 1327 // ----------- S t a t e ------------- | 1339 // ----------- S t a t e ------------- |
| 1328 // -- rax : receiver | 1340 // -- rax : receiver |
| 1329 // -- rcx : name | 1341 // -- rcx : name |
| 1330 // -- rsp[0] : return address | 1342 // -- rsp[0] : return address |
| 1331 // ----------------------------------- | 1343 // ----------------------------------- |
| 1332 { | 1344 { |
| 1333 FrameScope scope(masm, StackFrame::INTERNAL); | 1345 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1334 | 1346 |
| 1335 if (!getter.is_null()) { | 1347 if (!getter.is_null()) { |
| 1336 // Call the JavaScript getter with the receiver on the stack. | 1348 // Call the JavaScript getter with the receiver on the stack. |
| 1349 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 1350 // Swap in the global receiver. |
| 1351 __ movp(receiver, |
| 1352 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); |
| 1353 } |
| 1337 __ push(receiver); | 1354 __ push(receiver); |
| 1338 ParameterCount actual(0); | 1355 ParameterCount actual(0); |
| 1339 ParameterCount expected(getter); | 1356 ParameterCount expected(getter); |
| 1340 __ InvokeFunction(getter, expected, actual, | 1357 __ InvokeFunction(getter, expected, actual, |
| 1341 CALL_FUNCTION, NullCallWrapper()); | 1358 CALL_FUNCTION, NullCallWrapper()); |
| 1342 } else { | 1359 } else { |
| 1343 // If we generate a global code snippet for deoptimization only, remember | 1360 // If we generate a global code snippet for deoptimization only, remember |
| 1344 // the place to continue after deoptimization. | 1361 // the place to continue after deoptimization. |
| 1345 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | 1362 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
| 1346 } | 1363 } |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 // ----------------------------------- | 1502 // ----------------------------------- |
| 1486 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1503 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1487 } | 1504 } |
| 1488 | 1505 |
| 1489 | 1506 |
| 1490 #undef __ | 1507 #undef __ |
| 1491 | 1508 |
| 1492 } } // namespace v8::internal | 1509 } } // namespace v8::internal |
| 1493 | 1510 |
| 1494 #endif // V8_TARGET_ARCH_X64 | 1511 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |