| 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.h" | 11 #include "vm/flow_graph.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/locations.h" | 13 #include "vm/locations.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/parser.h" | 15 #include "vm/parser.h" |
| 16 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
| 17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 18 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 19 | 19 |
| 20 #define __ compiler->assembler()-> | 20 #define __ compiler->assembler()-> |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DECLARE_FLAG(bool, emit_edge_counters); | 24 DECLARE_FLAG(bool, emit_edge_counters); |
| 25 DECLARE_FLAG(int, optimization_counter_threshold); | 25 DECLARE_FLAG(int, optimization_counter_threshold); |
| 26 DECLARE_FLAG(bool, propagate_ic_data); | 26 DECLARE_FLAG(bool, propagate_ic_data); |
| 27 DECLARE_FLAG(bool, use_osr); | 27 DECLARE_FLAG(bool, use_osr); |
| 28 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 28 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 29 DECLARE_FLAG(bool, use_slow_path); | |
| 30 | 29 |
| 31 // Generic summary for call instructions that have all arguments pushed | 30 // Generic summary for call instructions that have all arguments pushed |
| 32 // on the stack and return the result in a fixed register EAX. | 31 // on the stack and return the result in a fixed register EAX. |
| 33 LocationSummary* Instruction::MakeCallSummary() { | 32 LocationSummary* Instruction::MakeCallSummary() { |
| 34 Isolate* isolate = Isolate::Current(); | 33 Isolate* isolate = Isolate::Current(); |
| 35 LocationSummary* result = new(isolate) LocationSummary( | 34 LocationSummary* result = new(isolate) LocationSummary( |
| 36 isolate, 0, 0, LocationSummary::kCall); | 35 isolate, 0, 0, LocationSummary::kCall); |
| 37 result->set_out(0, Location::RegisterLocation(EAX)); | 36 result->set_out(0, Location::RegisterLocation(EAX)); |
| 38 return result; | 37 return result; |
| 39 } | 38 } |
| (...skipping 1994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2034 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); | 2033 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2035 locs->set_in(0, Location::RegisterLocation(ECX)); | 2034 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 2036 locs->set_in(1, Location::RegisterLocation(EDX)); | 2035 locs->set_in(1, Location::RegisterLocation(EDX)); |
| 2037 locs->set_out(0, Location::RegisterLocation(EAX)); | 2036 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2038 return locs; | 2037 return locs; |
| 2039 } | 2038 } |
| 2040 | 2039 |
| 2041 | 2040 |
| 2042 // Inlines array allocation for known constant values. | 2041 // Inlines array allocation for known constant values. |
| 2043 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2042 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 2044 intptr_t num_elements, | 2043 intptr_t num_elements, |
| 2045 Label* slow_path, | 2044 Label* slow_path, |
| 2046 Label* done) { | 2045 Label* done) { |
| 2047 const Register kLengthReg = EDX; | 2046 const Register kLengthReg = EDX; |
| 2048 const Register kElemTypeReg = ECX; | 2047 const Register kElemTypeReg = ECX; |
| 2049 const intptr_t kArraySize = Array::InstanceSize(num_elements); | 2048 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 2050 Isolate* isolate = Isolate::Current(); | |
| 2051 Heap* heap = isolate->heap(); | |
| 2052 | 2049 |
| 2053 __ movl(EAX, Address::Absolute(heap->TopAddress())); | 2050 // Instance in EAX. |
| 2054 __ movl(EBX, EAX); | 2051 // Object end address in EBX. |
| 2055 | 2052 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump, |
| 2056 __ addl(EBX, Immediate(kArraySize)); | 2053 EAX, // instance |
| 2057 __ j(CARRY, slow_path); | 2054 EBX); // end address |
| 2058 | |
| 2059 // Check if the allocation fits into the remaining space. | |
| 2060 // EAX: potential new object start. | |
| 2061 // EBX: potential next object start. | |
| 2062 __ cmpl(EBX, Address::Absolute(heap->EndAddress())); | |
| 2063 __ j(ABOVE_EQUAL, slow_path); | |
| 2064 | |
| 2065 // Successfully allocated the object(s), now update top to point to | |
| 2066 // next object start and initialize the object. | |
| 2067 __ movl(Address::Absolute(heap->TopAddress()), EBX); | |
| 2068 __ addl(EAX, Immediate(kHeapObjectTag)); | |
| 2069 __ UpdateAllocationStatsWithSize(kArrayCid, kArraySize, kNoRegister); | |
| 2070 | |
| 2071 // Initialize the tags. | |
| 2072 // EAX: new object start as a tagged pointer. | |
| 2073 { | |
| 2074 uword tags = 0; | |
| 2075 tags = RawObject::ClassIdTag::update(kArrayCid, tags); | |
| 2076 tags = RawObject::SizeTag::update(kArraySize, tags); | |
| 2077 __ movl(FieldAddress(EAX, Array::tags_offset()), Immediate(tags)); | |
| 2078 } | |
| 2079 | 2055 |
| 2080 // Store the type argument field. | 2056 // Store the type argument field. |
| 2081 __ StoreIntoObjectNoBarrier(EAX, | 2057 __ StoreIntoObjectNoBarrier(EAX, |
| 2082 FieldAddress(EAX, Array::type_arguments_offset()), | 2058 FieldAddress(EAX, Array::type_arguments_offset()), |
| 2083 kElemTypeReg); | 2059 kElemTypeReg); |
| 2084 | 2060 |
| 2085 // Set the length field. | 2061 // Set the length field. |
| 2086 __ StoreIntoObjectNoBarrier(EAX, | 2062 __ StoreIntoObjectNoBarrier(EAX, |
| 2087 FieldAddress(EAX, Array::length_offset()), | 2063 FieldAddress(EAX, Array::length_offset()), |
| 2088 kLengthReg); | 2064 kLengthReg); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2370 deopt_id(), | 2346 deopt_id(), |
| 2371 kInstantiateTypeArgumentsRuntimeEntry, | 2347 kInstantiateTypeArgumentsRuntimeEntry, |
| 2372 2, | 2348 2, |
| 2373 locs()); | 2349 locs()); |
| 2374 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2350 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 2375 __ popl(result_reg); // Pop instantiated type arguments. | 2351 __ popl(result_reg); // Pop instantiated type arguments. |
| 2376 __ Bind(&type_arguments_instantiated); | 2352 __ Bind(&type_arguments_instantiated); |
| 2377 } | 2353 } |
| 2378 | 2354 |
| 2379 | 2355 |
| 2380 LocationSummary* AllocateContextInstr::MakeLocationSummary(Isolate* isolate, | 2356 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2381 bool opt) const { | 2357 Isolate* isolate, |
| 2382 if (opt) { | 2358 bool opt) const { |
| 2383 const intptr_t kNumInputs = 0; | 2359 ASSERT(opt); |
| 2384 const intptr_t kNumTemps = 2; | |
| 2385 LocationSummary* locs = new(isolate) LocationSummary( | |
| 2386 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | |
| 2387 locs->set_temp(0, Location::RegisterLocation(ECX)); | |
| 2388 locs->set_temp(1, Location::RegisterLocation(EBX)); | |
| 2389 locs->set_out(0, Location::RegisterLocation(EAX)); | |
| 2390 return locs; | |
| 2391 } | |
| 2392 const intptr_t kNumInputs = 0; | 2360 const intptr_t kNumInputs = 0; |
| 2393 const intptr_t kNumTemps = 1; | 2361 const intptr_t kNumTemps = 1; |
| 2394 LocationSummary* locs = new(isolate) LocationSummary( | 2362 LocationSummary* locs = new(isolate) LocationSummary( |
| 2395 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); | 2363 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2396 locs->set_temp(0, Location::RegisterLocation(EDX)); | 2364 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 2397 locs->set_out(0, Location::RegisterLocation(EAX)); | 2365 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2398 return locs; | 2366 return locs; |
| 2399 } | 2367 } |
| 2400 | 2368 |
| 2401 | 2369 |
| 2402 class AllocateContextSlowPath : public SlowPathCode { | 2370 class AllocateContextSlowPath : public SlowPathCode { |
| 2403 public: | 2371 public: |
| 2404 explicit AllocateContextSlowPath(AllocateContextInstr* instruction) | 2372 explicit AllocateContextSlowPath( |
| 2373 AllocateUninitializedContextInstr* instruction) |
| 2405 : instruction_(instruction) { } | 2374 : instruction_(instruction) { } |
| 2406 | 2375 |
| 2407 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2376 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2408 __ Comment("AllocateContextSlowPath"); | 2377 __ Comment("AllocateContextSlowPath"); |
| 2409 __ Bind(entry_label()); | 2378 __ Bind(entry_label()); |
| 2410 | 2379 |
| 2411 LocationSummary* locs = instruction_->locs(); | 2380 LocationSummary* locs = instruction_->locs(); |
| 2412 ASSERT(!locs->live_registers()->Contains(locs->out(0))); | 2381 ASSERT(!locs->live_registers()->Contains(locs->out(0))); |
| 2413 | 2382 |
| 2414 compiler->SaveLiveRegisters(locs); | 2383 compiler->SaveLiveRegisters(locs); |
| 2415 | 2384 |
| 2416 __ movl(EDX, Immediate(instruction_->num_context_variables())); | 2385 __ movl(EDX, Immediate(instruction_->num_context_variables())); |
| 2417 StubCode* stub_code = compiler->isolate()->stub_code(); | 2386 StubCode* stub_code = compiler->isolate()->stub_code(); |
| 2418 const ExternalLabel label(stub_code->AllocateContextEntryPoint()); | 2387 const ExternalLabel label(stub_code->AllocateContextEntryPoint()); |
| 2419 compiler->GenerateCall(instruction_->token_pos(), | 2388 compiler->GenerateCall(instruction_->token_pos(), |
| 2420 &label, | 2389 &label, |
| 2421 RawPcDescriptors::kOther, | 2390 RawPcDescriptors::kOther, |
| 2422 locs); | 2391 locs); |
| 2423 ASSERT(instruction_->locs()->out(0).reg() == EAX); | 2392 ASSERT(instruction_->locs()->out(0).reg() == EAX); |
| 2424 compiler->RestoreLiveRegisters(instruction_->locs()); | 2393 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2425 __ jmp(exit_label()); | 2394 __ jmp(exit_label()); |
| 2426 } | 2395 } |
| 2427 | 2396 |
| 2428 private: | 2397 private: |
| 2429 AllocateContextInstr* instruction_; | 2398 AllocateUninitializedContextInstr* instruction_; |
| 2430 }; | 2399 }; |
| 2431 | 2400 |
| 2432 | 2401 |
| 2402 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2403 FlowGraphCompiler* compiler) { |
| 2404 ASSERT(compiler->is_optimizing()); |
| 2405 Register temp = locs()->temp(0).reg(); |
| 2406 Register result = locs()->out(0).reg(); |
| 2407 // Try allocate the object. |
| 2408 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2409 compiler->AddSlowPathCode(slow_path); |
| 2410 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2411 |
| 2412 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2413 Assembler::kFarJump, |
| 2414 result, // instance |
| 2415 temp); // end address |
| 2416 |
| 2417 // Setup up number of context variables field. |
| 2418 __ movl(FieldAddress(result, Context::num_variables_offset()), |
| 2419 Immediate(num_context_variables())); |
| 2420 |
| 2421 // Setup isolate field. |
| 2422 __ movl(FieldAddress(result, Context::isolate_offset()), |
| 2423 Immediate(reinterpret_cast<int32_t>(Isolate::Current()))); |
| 2424 |
| 2425 __ Bind(slow_path->exit_label()); |
| 2426 } |
| 2427 |
| 2428 |
| 2429 LocationSummary* AllocateContextInstr::MakeLocationSummary(Isolate* isolate, |
| 2430 bool opt) const { |
| 2431 const intptr_t kNumInputs = 0; |
| 2432 const intptr_t kNumTemps = 1; |
| 2433 LocationSummary* locs = new(isolate) LocationSummary( |
| 2434 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2435 locs->set_temp(0, Location::RegisterLocation(EDX)); |
| 2436 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2437 return locs; |
| 2438 } |
| 2439 |
| 2433 | 2440 |
| 2434 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2441 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2435 if (compiler->is_optimizing()) { | |
| 2436 Register temp0 = locs()->temp(0).reg(); | |
| 2437 Register temp1 = locs()->temp(1).reg(); | |
| 2438 Register result = locs()->out(0).reg(); | |
| 2439 // Try allocate the object. | |
| 2440 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | |
| 2441 compiler->AddSlowPathCode(slow_path); | |
| 2442 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | |
| 2443 __ movl(temp1, Immediate(instance_size)); | |
| 2444 Isolate* isolate = Isolate::Current(); | |
| 2445 Heap* heap = isolate->heap(); | |
| 2446 __ movl(result, Address::Absolute(heap->TopAddress())); | |
| 2447 __ addl(temp1, result); | |
| 2448 // Check if the allocation fits into the remaining space. | |
| 2449 // EAX: potential new object. | |
| 2450 // EBX: potential next object start. | |
| 2451 __ cmpl(temp1, Address::Absolute(heap->EndAddress())); | |
| 2452 if (FLAG_use_slow_path) { | |
| 2453 __ jmp(slow_path->entry_label()); | |
| 2454 } else { | |
| 2455 __ j(ABOVE_EQUAL, slow_path->entry_label()); | |
| 2456 } | |
| 2457 | |
| 2458 // Successfully allocated the object, now update top to point to | |
| 2459 // next object start and initialize the object. | |
| 2460 // EAX: new object. | |
| 2461 // EBX: next object start. | |
| 2462 // EDX: number of context variables. | |
| 2463 __ movl(Address::Absolute(heap->TopAddress()), temp1); | |
| 2464 __ addl(result, Immediate(kHeapObjectTag)); | |
| 2465 __ UpdateAllocationStatsWithSize(kContextCid, instance_size, kNoRegister); | |
| 2466 | |
| 2467 // Calculate the size tag and write tags. | |
| 2468 intptr_t size_tag = (instance_size > RawObject::SizeTag::kMaxSizeTag) | |
| 2469 ? 0 : instance_size << (RawObject::kSizeTagPos - kObjectAlignmentLog2); | |
| 2470 | |
| 2471 intptr_t tags = size_tag | RawObject::ClassIdTag::encode(kContextCid); | |
| 2472 __ movl(FieldAddress(result, Context::tags_offset()), Immediate(tags)); | |
| 2473 | |
| 2474 // Setup up number of context variables field. | |
| 2475 // EAX: new object. | |
| 2476 __ movl(FieldAddress(result, Context::num_variables_offset()), | |
| 2477 Immediate(num_context_variables())); | |
| 2478 | |
| 2479 // Setup isolate field. | |
| 2480 __ movl(FieldAddress(result, Context::isolate_offset()), | |
| 2481 Immediate(reinterpret_cast<int32_t>(isolate))); | |
| 2482 | |
| 2483 // Setup the parent field. | |
| 2484 const Immediate& raw_null = | |
| 2485 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 2486 __ movl(FieldAddress(result, Context::parent_offset()), raw_null); | |
| 2487 | |
| 2488 // Initialize the context variables. | |
| 2489 // EAX: new object. | |
| 2490 if (num_context_variables() > 0) { | |
| 2491 Label loop; | |
| 2492 __ leal(temp1, FieldAddress(result, Context::variable_offset(0))); | |
| 2493 __ movl(temp0, Immediate(num_context_variables())); | |
| 2494 __ Bind(&loop); | |
| 2495 __ decl(temp0); | |
| 2496 __ movl(Address(temp1, temp0, TIMES_4, 0), raw_null); | |
| 2497 __ j(NOT_ZERO, &loop, Assembler::kNearJump); | |
| 2498 } | |
| 2499 // EAX: new object. | |
| 2500 __ Bind(slow_path->exit_label()); | |
| 2501 return; | |
| 2502 } | |
| 2503 | |
| 2504 ASSERT(locs()->temp(0).reg() == EDX); | 2442 ASSERT(locs()->temp(0).reg() == EDX); |
| 2505 ASSERT(locs()->out(0).reg() == EAX); | 2443 ASSERT(locs()->out(0).reg() == EAX); |
| 2506 | 2444 |
| 2507 __ movl(EDX, Immediate(num_context_variables())); | 2445 __ movl(EDX, Immediate(num_context_variables())); |
| 2508 StubCode* stub_code = compiler->isolate()->stub_code(); | 2446 StubCode* stub_code = compiler->isolate()->stub_code(); |
| 2509 const ExternalLabel label(stub_code->AllocateContextEntryPoint()); | 2447 const ExternalLabel label(stub_code->AllocateContextEntryPoint()); |
| 2510 compiler->GenerateCall(token_pos(), | 2448 compiler->GenerateCall(token_pos(), |
| 2511 &label, | 2449 &label, |
| 2512 RawPcDescriptors::kOther, | 2450 RawPcDescriptors::kOther, |
| 2513 locs()); | 2451 locs()); |
| (...skipping 4042 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6556 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6494 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
| 6557 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6495 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
| 6558 #endif | 6496 #endif |
| 6559 } | 6497 } |
| 6560 | 6498 |
| 6561 } // namespace dart | 6499 } // namespace dart |
| 6562 | 6500 |
| 6563 #undef __ | 6501 #undef __ |
| 6564 | 6502 |
| 6565 #endif // defined TARGET_ARCH_IA32 | 6503 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |