| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 break; | 303 break; |
| 304 default: | 304 default: |
| 305 UNREACHABLE(); | 305 UNREACHABLE(); |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 } | 308 } |
| 309 | 309 |
| 310 | 310 |
| 311 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 311 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 312 bool opt) const { | 312 bool opt) const { |
| 313 const intptr_t kNumInputs = 2; | 313 const intptr_t kNumInputs = 3; |
| 314 const intptr_t kNumTemps = 0; | 314 const intptr_t kNumTemps = 0; |
| 315 LocationSummary* summary = new (zone) | 315 LocationSummary* summary = new (zone) |
| 316 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 316 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 317 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. | 317 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. |
| 318 summary->set_in(1, Location::RegisterLocation(RDX)); // Type arguments. | 318 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. |
| 319 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. |
| 319 summary->set_out(0, Location::RegisterLocation(RAX)); | 320 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 320 return summary; | 321 return summary; |
| 321 } | 322 } |
| 322 | 323 |
| 323 | 324 |
| 324 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 325 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 325 bool opt) const { | 326 bool opt) const { |
| 326 const intptr_t kNumInputs = 1; | 327 const intptr_t kNumInputs = 1; |
| 327 const intptr_t kNumTemps = 0; | 328 const intptr_t kNumTemps = 0; |
| 328 LocationSummary* locs = new (zone) | 329 LocationSummary* locs = new (zone) |
| (...skipping 1698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2027 value, CanValueBeSmi()); | 2028 value, CanValueBeSmi()); |
| 2028 } else { | 2029 } else { |
| 2029 __ StoreIntoObjectNoBarrier( | 2030 __ StoreIntoObjectNoBarrier( |
| 2030 temp, FieldAddress(temp, Field::static_value_offset()), value); | 2031 temp, FieldAddress(temp, Field::static_value_offset()), value); |
| 2031 } | 2032 } |
| 2032 } | 2033 } |
| 2033 | 2034 |
| 2034 | 2035 |
| 2035 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2036 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 2036 bool opt) const { | 2037 bool opt) const { |
| 2037 const intptr_t kNumInputs = 2; | 2038 const intptr_t kNumInputs = 3; |
| 2038 const intptr_t kNumTemps = 0; | 2039 const intptr_t kNumTemps = 0; |
| 2039 LocationSummary* summary = new (zone) | 2040 LocationSummary* summary = new (zone) |
| 2040 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2041 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2041 summary->set_in(0, Location::RegisterLocation(RAX)); | 2042 summary->set_in(0, Location::RegisterLocation(RAX)); // Instance. |
| 2042 summary->set_in(1, Location::RegisterLocation(RDX)); | 2043 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. |
| 2044 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. |
| 2043 summary->set_out(0, Location::RegisterLocation(RAX)); | 2045 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 2044 return summary; | 2046 return summary; |
| 2045 } | 2047 } |
| 2046 | 2048 |
| 2047 | 2049 |
| 2048 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2050 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2049 ASSERT(locs()->in(0).reg() == RAX); // Value. | 2051 ASSERT(locs()->in(0).reg() == RAX); // Value. |
| 2050 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. | 2052 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. |
| 2053 ASSERT(locs()->in(2).reg() == RCX); // Function type arguments. |
| 2051 | 2054 |
| 2052 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); | 2055 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); |
| 2053 ASSERT(locs()->out(0).reg() == RAX); | 2056 ASSERT(locs()->out(0).reg() == RAX); |
| 2054 } | 2057 } |
| 2055 | 2058 |
| 2056 | 2059 |
| 2057 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and | 2060 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and |
| 2058 // use slow path stub. | 2061 // use slow path stub. |
| 2059 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2062 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 2060 bool opt) const { | 2063 bool opt) const { |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2281 | 2284 |
| 2282 __ Bind(&load_pointer); | 2285 __ Bind(&load_pointer); |
| 2283 } | 2286 } |
| 2284 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); | 2287 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); |
| 2285 __ Bind(&done); | 2288 __ Bind(&done); |
| 2286 } | 2289 } |
| 2287 | 2290 |
| 2288 | 2291 |
| 2289 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2292 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2290 bool opt) const { | 2293 bool opt) const { |
| 2291 const intptr_t kNumInputs = 1; | 2294 const intptr_t kNumInputs = 2; |
| 2292 const intptr_t kNumTemps = 0; | 2295 const intptr_t kNumTemps = 0; |
| 2293 LocationSummary* locs = new (zone) | 2296 LocationSummary* locs = new (zone) |
| 2294 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2297 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2295 locs->set_in(0, Location::RegisterLocation(RAX)); | 2298 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. |
| 2299 locs->set_in(1, Location::RegisterLocation(RDX)); // Function type args. |
| 2296 locs->set_out(0, Location::RegisterLocation(RAX)); | 2300 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2297 return locs; | 2301 return locs; |
| 2298 } | 2302 } |
| 2299 | 2303 |
| 2300 | 2304 |
| 2301 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2305 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2302 Register instantiator_reg = locs()->in(0).reg(); | 2306 Register instantiator_type_args_reg = locs()->in(0).reg(); |
| 2307 Register function_type_args_reg = locs()->in(1).reg(); |
| 2303 Register result_reg = locs()->out(0).reg(); | 2308 Register result_reg = locs()->out(0).reg(); |
| 2304 | 2309 |
| 2305 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2310 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
| 2311 // 'function_type_args_reg' is a TypeArguments object (or null). |
| 2306 // A runtime call to instantiate the type is required. | 2312 // A runtime call to instantiate the type is required. |
| 2307 __ PushObject(Object::null_object()); // Make room for the result. | 2313 __ PushObject(Object::null_object()); // Make room for the result. |
| 2308 __ PushObject(type()); | 2314 __ PushObject(type()); |
| 2309 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2315 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. |
| 2316 __ pushq(function_type_args_reg); // Push function type arguments. |
| 2310 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2317 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2311 kInstantiateTypeRuntimeEntry, 2, locs()); | 2318 kInstantiateTypeRuntimeEntry, 3, locs()); |
| 2312 __ Drop(2); // Drop instantiator and uninstantiated type. | 2319 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. |
| 2313 __ popq(result_reg); // Pop instantiated type. | 2320 __ popq(result_reg); // Pop instantiated type. |
| 2314 ASSERT(instantiator_reg == result_reg); | |
| 2315 } | 2321 } |
| 2316 | 2322 |
| 2317 | 2323 |
| 2318 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2324 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2319 Zone* zone, | 2325 Zone* zone, |
| 2320 bool opt) const { | 2326 bool opt) const { |
| 2321 const intptr_t kNumInputs = 1; | 2327 const intptr_t kNumInputs = 2; |
| 2322 const intptr_t kNumTemps = 0; | 2328 const intptr_t kNumTemps = 0; |
| 2323 LocationSummary* locs = new (zone) | 2329 LocationSummary* locs = new (zone) |
| 2324 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2330 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2325 locs->set_in(0, Location::RegisterLocation(RAX)); | 2331 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. |
| 2332 locs->set_in(1, Location::RegisterLocation(RCX)); // Function type args. |
| 2326 locs->set_out(0, Location::RegisterLocation(RAX)); | 2333 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2327 return locs; | 2334 return locs; |
| 2328 } | 2335 } |
| 2329 | 2336 |
| 2330 | 2337 |
| 2331 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2338 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2332 FlowGraphCompiler* compiler) { | 2339 FlowGraphCompiler* compiler) { |
| 2333 Register instantiator_reg = locs()->in(0).reg(); | 2340 Register instantiator_type_args_reg = locs()->in(0).reg(); |
| 2341 Register function_type_args_reg = locs()->in(1).reg(); |
| 2334 Register result_reg = locs()->out(0).reg(); | 2342 Register result_reg = locs()->out(0).reg(); |
| 2335 ASSERT(instantiator_reg == RAX); | 2343 ASSERT(instantiator_type_args_reg == RAX); |
| 2336 ASSERT(instantiator_reg == result_reg); | 2344 ASSERT(instantiator_type_args_reg == result_reg); |
| 2337 | 2345 |
| 2338 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2346 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
| 2347 // 'function_type_args_reg' is a TypeArguments object (or null). |
| 2339 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2348 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 2340 !type_arguments().CanShareInstantiatorTypeArguments( | 2349 !type_arguments().CanShareInstantiatorTypeArguments( |
| 2341 instantiator_class())); | 2350 instantiator_class())); |
| 2342 // If the instantiator is null and if the type argument vector | 2351 // If both the instantiator and function type arguments are null and if the |
| 2343 // instantiated from null becomes a vector of dynamic, then use null as | 2352 // type argument vector instantiated from null becomes a vector of dynamic, |
| 2344 // the type arguments. | 2353 // then use null as the type arguments. |
| 2345 Label type_arguments_instantiated; | 2354 Label type_arguments_instantiated; |
| 2346 const intptr_t len = type_arguments().Length(); | 2355 const intptr_t len = type_arguments().Length(); |
| 2347 if (type_arguments().IsRawInstantiatedRaw(len)) { | 2356 if (type_arguments().IsRawWhenInstantiatedFromRaw(len)) { |
| 2348 __ CompareObject(instantiator_reg, Object::null_object()); | 2357 Label non_null_type_args; |
| 2358 __ CompareObject(instantiator_type_args_reg, Object::null_object()); |
| 2359 __ j(NOT_EQUAL, &non_null_type_args, Assembler::kNearJump); |
| 2360 __ CompareObject(function_type_args_reg, Object::null_object()); |
| 2349 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2361 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2362 __ Bind(&non_null_type_args); |
| 2350 } | 2363 } |
| 2351 | 2364 |
| 2352 // Lookup cache before calling runtime. | 2365 // Lookup cache before calling runtime. |
| 2353 // TODO(fschneider): Consider moving this into a shared stub to reduce | 2366 // TODO(regis): Consider moving this into a shared stub to reduce |
| 2354 // generated code size. | 2367 // generated code size. |
| 2355 __ LoadObject(RDI, type_arguments()); | 2368 __ LoadObject(RDI, type_arguments()); |
| 2356 __ movq(RDI, FieldAddress(RDI, TypeArguments::instantiations_offset())); | 2369 __ movq(RDI, FieldAddress(RDI, TypeArguments::instantiations_offset())); |
| 2357 __ leaq(RDI, FieldAddress(RDI, Array::data_offset())); | 2370 __ leaq(RDI, FieldAddress(RDI, Array::data_offset())); |
| 2358 // The instantiations cache is initialized with Object::zero_array() and is | 2371 // The instantiations cache is initialized with Object::zero_array() and is |
| 2359 // therefore guaranteed to contain kNoInstantiator. No length check needed. | 2372 // therefore guaranteed to contain kNoInstantiator. No length check needed. |
| 2360 Label loop, found, slow_case; | 2373 Label loop, next, found, slow_case; |
| 2361 __ Bind(&loop); | 2374 __ Bind(&loop); |
| 2362 __ movq(RDX, Address(RDI, 0 * kWordSize)); // Cached instantiator. | 2375 __ movq(RDX, Address(RDI, 0 * kWordSize)); // Cached instantiator type args. |
| 2363 __ cmpq(RDX, RAX); | 2376 __ cmpq(RDX, instantiator_type_args_reg); |
| 2377 __ j(NOT_EQUAL, &next, Assembler::kNearJump); |
| 2378 __ movq(R10, Address(RDI, 1 * kWordSize)); // Cached function type args. |
| 2379 __ cmpq(R10, function_type_args_reg); |
| 2364 __ j(EQUAL, &found, Assembler::kNearJump); | 2380 __ j(EQUAL, &found, Assembler::kNearJump); |
| 2365 __ addq(RDI, Immediate(2 * kWordSize)); | 2381 __ Bind(&next); |
| 2382 __ addq(RDI, Immediate(StubCode::kInstantiationSizeInWords * kWordSize)); |
| 2366 __ cmpq(RDX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 2383 __ cmpq(RDX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2367 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 2384 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 2368 __ jmp(&slow_case, Assembler::kNearJump); | 2385 __ jmp(&slow_case, Assembler::kNearJump); |
| 2369 __ Bind(&found); | 2386 __ Bind(&found); |
| 2370 __ movq(RAX, Address(RDI, 1 * kWordSize)); // Cached instantiated args. | 2387 __ movq(result_reg, Address(RDI, 2 * kWordSize)); // Cached instantiated ta. |
| 2371 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); | 2388 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); |
| 2372 | 2389 |
| 2373 __ Bind(&slow_case); | 2390 __ Bind(&slow_case); |
| 2374 // Instantiate non-null type arguments. | 2391 // Instantiate non-null type arguments. |
| 2375 // A runtime call to instantiate the type arguments is required. | 2392 // A runtime call to instantiate the type arguments is required. |
| 2376 __ PushObject(Object::null_object()); // Make room for the result. | 2393 __ PushObject(Object::null_object()); // Make room for the result. |
| 2377 __ PushObject(type_arguments()); | 2394 __ PushObject(type_arguments()); |
| 2378 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2395 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. |
| 2396 __ pushq(function_type_args_reg); // Push function type arguments. |
| 2379 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2397 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2380 kInstantiateTypeArgumentsRuntimeEntry, 2, | 2398 kInstantiateTypeArgumentsRuntimeEntry, 3, |
| 2381 locs()); | 2399 locs()); |
| 2382 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2400 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. |
| 2383 __ popq(result_reg); // Pop instantiated type arguments. | 2401 __ popq(result_reg); // Pop instantiated type arguments. |
| 2384 __ Bind(&type_arguments_instantiated); | 2402 __ Bind(&type_arguments_instantiated); |
| 2385 ASSERT(instantiator_reg == result_reg); | |
| 2386 } | 2403 } |
| 2387 | 2404 |
| 2388 | 2405 |
| 2389 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2406 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2390 Zone* zone, | 2407 Zone* zone, |
| 2391 bool opt) const { | 2408 bool opt) const { |
| 2392 ASSERT(opt); | 2409 ASSERT(opt); |
| 2393 const intptr_t kNumInputs = 0; | 2410 const intptr_t kNumInputs = 0; |
| 2394 const intptr_t kNumTemps = 2; | 2411 const intptr_t kNumTemps = 2; |
| 2395 LocationSummary* locs = new (zone) LocationSummary( | 2412 LocationSummary* locs = new (zone) LocationSummary( |
| (...skipping 4389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6785 __ Drop(1); | 6802 __ Drop(1); |
| 6786 __ popq(result); | 6803 __ popq(result); |
| 6787 } | 6804 } |
| 6788 | 6805 |
| 6789 | 6806 |
| 6790 } // namespace dart | 6807 } // namespace dart |
| 6791 | 6808 |
| 6792 #undef __ | 6809 #undef __ |
| 6793 | 6810 |
| 6794 #endif // defined TARGET_ARCH_X64 | 6811 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |