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 |