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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
13 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
15 #include "vm/stack_frame.h" | 15 #include "vm/stack_frame.h" |
16 #include "vm/stub_code.h" | 16 #include "vm/stub_code.h" |
17 #include "vm/symbols.h" | 17 #include "vm/symbols.h" |
18 | 18 |
19 #define __ compiler->assembler()-> | 19 #define __ compiler->assembler()-> |
20 | 20 |
21 namespace dart { | 21 namespace dart { |
22 | 22 |
23 DECLARE_FLAG(int, optimization_counter_threshold); | 23 DECLARE_FLAG(int, optimization_counter_threshold); |
24 DECLARE_FLAG(bool, propagate_ic_data); | 24 DECLARE_FLAG(bool, propagate_ic_data); |
25 DECLARE_FLAG(bool, use_osr); | 25 DECLARE_FLAG(bool, use_osr); |
26 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 26 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 27 DECLARE_FLAG(bool, use_slow_path); |
27 | 28 |
28 // Generic summary for call instructions that have all arguments pushed | 29 // Generic summary for call instructions that have all arguments pushed |
29 // on the stack and return the result in a fixed register EAX. | 30 // on the stack and return the result in a fixed register EAX. |
30 LocationSummary* Instruction::MakeCallSummary() { | 31 LocationSummary* Instruction::MakeCallSummary() { |
31 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); | 32 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
32 result->set_out(Location::RegisterLocation(EAX)); | 33 result->set_out(Location::RegisterLocation(EAX)); |
33 return result; | 34 return result; |
34 } | 35 } |
35 | 36 |
36 | 37 |
(...skipping 2211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2248 kInstantiateTypeArgumentsRuntimeEntry, | 2249 kInstantiateTypeArgumentsRuntimeEntry, |
2249 2, | 2250 2, |
2250 locs()); | 2251 locs()); |
2251 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2252 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
2252 __ popl(result_reg); // Pop instantiated type arguments. | 2253 __ popl(result_reg); // Pop instantiated type arguments. |
2253 __ Bind(&type_arguments_instantiated); | 2254 __ Bind(&type_arguments_instantiated); |
2254 } | 2255 } |
2255 | 2256 |
2256 | 2257 |
2257 LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const { | 2258 LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const { |
| 2259 if (opt) { |
| 2260 const intptr_t kNumInputs = 0; |
| 2261 const intptr_t kNumTemps = 2; |
| 2262 LocationSummary* locs = new LocationSummary( |
| 2263 kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2264 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 2265 locs->set_temp(1, Location::RegisterLocation(EBX)); |
| 2266 locs->set_out(Location::RegisterLocation(EAX)); |
| 2267 return locs; |
| 2268 } |
2258 const intptr_t kNumInputs = 0; | 2269 const intptr_t kNumInputs = 0; |
2259 const intptr_t kNumTemps = 1; | 2270 const intptr_t kNumTemps = 1; |
2260 LocationSummary* locs = | 2271 LocationSummary* locs = |
2261 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2272 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
2262 locs->set_temp(0, Location::RegisterLocation(EDX)); | 2273 locs->set_temp(0, Location::RegisterLocation(EDX)); |
2263 locs->set_out(Location::RegisterLocation(EAX)); | 2274 locs->set_out(Location::RegisterLocation(EAX)); |
2264 return locs; | 2275 return locs; |
2265 } | 2276 } |
2266 | 2277 |
2267 | 2278 |
| 2279 class AllocateContextSlowPath : public SlowPathCode { |
| 2280 public: |
| 2281 explicit AllocateContextSlowPath(AllocateContextInstr* instruction) |
| 2282 : instruction_(instruction) { } |
| 2283 |
| 2284 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2285 __ Comment("AllocateContextSlowPath"); |
| 2286 __ Bind(entry_label()); |
| 2287 |
| 2288 LocationSummary* locs = instruction_->locs(); |
| 2289 locs->live_registers()->Remove(locs->out()); |
| 2290 |
| 2291 compiler->SaveLiveRegisters(locs); |
| 2292 |
| 2293 __ movl(EDX, Immediate(instruction_->num_context_variables())); |
| 2294 const ExternalLabel label("alloc_context", |
| 2295 StubCode::AllocateContextEntryPoint()); |
| 2296 compiler->GenerateCall(instruction_->token_pos(), |
| 2297 &label, |
| 2298 PcDescriptors::kOther, |
| 2299 locs); |
| 2300 ASSERT(instruction_->locs()->out().reg() == EAX); |
| 2301 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2302 __ jmp(exit_label()); |
| 2303 } |
| 2304 |
| 2305 private: |
| 2306 AllocateContextInstr* instruction_; |
| 2307 }; |
| 2308 |
| 2309 |
| 2310 |
2268 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2311 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2312 if (compiler->is_optimizing()) { |
| 2313 Register temp0 = locs()->temp(0).reg(); |
| 2314 Register temp1 = locs()->temp(1).reg(); |
| 2315 Register result = locs()->out().reg(); |
| 2316 // Try allocate the object. |
| 2317 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2318 compiler->AddSlowPathCode(slow_path); |
| 2319 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2320 __ movl(temp1, Immediate(instance_size)); |
| 2321 Isolate* isolate = Isolate::Current(); |
| 2322 Heap* heap = isolate->heap(); |
| 2323 __ movl(result, Address::Absolute(heap->TopAddress())); |
| 2324 __ addl(temp1, result); |
| 2325 // Check if the allocation fits into the remaining space. |
| 2326 // EAX: potential new object. |
| 2327 // EBX: potential next object start. |
| 2328 __ cmpl(temp1, Address::Absolute(heap->EndAddress())); |
| 2329 if (FLAG_use_slow_path) { |
| 2330 __ jmp(slow_path->entry_label()); |
| 2331 } else { |
| 2332 __ j(ABOVE_EQUAL, slow_path->entry_label()); |
| 2333 } |
| 2334 |
| 2335 // Successfully allocated the object, now update top to point to |
| 2336 // next object start and initialize the object. |
| 2337 // EAX: new object. |
| 2338 // EBX: next object start. |
| 2339 // EDX: number of context variables. |
| 2340 __ movl(Address::Absolute(heap->TopAddress()), temp1); |
| 2341 __ addl(result, Immediate(kHeapObjectTag)); |
| 2342 __ UpdateAllocationStatsWithSize(kContextCid, instance_size, kNoRegister); |
| 2343 |
| 2344 // Calculate the size tag and write tags. |
| 2345 intptr_t size_tag = (instance_size > RawObject::SizeTag::kMaxSizeTag) |
| 2346 ? 0 : instance_size << (RawObject::kSizeTagBit - kObjectAlignmentLog2); |
| 2347 |
| 2348 intptr_t tags = size_tag | RawObject::ClassIdTag::encode(kContextCid); |
| 2349 __ movl(FieldAddress(result, Context::tags_offset()), Immediate(tags)); |
| 2350 |
| 2351 // Setup up number of context variables field. |
| 2352 // EAX: new object. |
| 2353 __ movl(FieldAddress(result, Context::num_variables_offset()), |
| 2354 Immediate(num_context_variables())); |
| 2355 |
| 2356 // Setup isolate field. |
| 2357 __ movl(FieldAddress(result, Context::isolate_offset()), |
| 2358 Immediate(reinterpret_cast<int32_t>(isolate))); |
| 2359 |
| 2360 // Setup the parent field. |
| 2361 const Immediate& raw_null = |
| 2362 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2363 __ movl(FieldAddress(result, Context::parent_offset()), raw_null); |
| 2364 |
| 2365 // Initialize the context variables. |
| 2366 // EAX: new object. |
| 2367 if (num_context_variables() > 0) { |
| 2368 Label loop; |
| 2369 __ leal(temp1, FieldAddress(result, Context::variable_offset(0))); |
| 2370 __ movl(temp0, Immediate(num_context_variables())); |
| 2371 __ Bind(&loop); |
| 2372 __ decl(temp0); |
| 2373 __ movl(Address(temp1, temp0, TIMES_4, 0), raw_null); |
| 2374 __ j(NOT_ZERO, &loop, Assembler::kNearJump); |
| 2375 } |
| 2376 // EAX: new object. |
| 2377 __ Bind(slow_path->exit_label()); |
| 2378 return; |
| 2379 } |
| 2380 |
2269 ASSERT(locs()->temp(0).reg() == EDX); | 2381 ASSERT(locs()->temp(0).reg() == EDX); |
2270 ASSERT(locs()->out().reg() == EAX); | 2382 ASSERT(locs()->out().reg() == EAX); |
2271 | 2383 |
2272 __ movl(EDX, Immediate(num_context_variables())); | 2384 __ movl(EDX, Immediate(num_context_variables())); |
2273 const ExternalLabel label("alloc_context", | 2385 const ExternalLabel label("alloc_context", |
2274 StubCode::AllocateContextEntryPoint()); | 2386 StubCode::AllocateContextEntryPoint()); |
2275 compiler->GenerateCall(token_pos(), | 2387 compiler->GenerateCall(token_pos(), |
2276 &label, | 2388 &label, |
2277 PcDescriptors::kOther, | 2389 PcDescriptors::kOther, |
2278 locs()); | 2390 locs()); |
(...skipping 3096 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5375 PcDescriptors::kOther, | 5487 PcDescriptors::kOther, |
5376 locs()); | 5488 locs()); |
5377 __ Drop(ArgumentCount()); // Discard arguments. | 5489 __ Drop(ArgumentCount()); // Discard arguments. |
5378 } | 5490 } |
5379 | 5491 |
5380 } // namespace dart | 5492 } // namespace dart |
5381 | 5493 |
5382 #undef __ | 5494 #undef __ |
5383 | 5495 |
5384 #endif // defined TARGET_ARCH_IA32 | 5496 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |