Index: runtime/vm/intermediate_language_ia32.cc |
=================================================================== |
--- runtime/vm/intermediate_language_ia32.cc (revision 8165) |
+++ runtime/vm/intermediate_language_ia32.cc (working copy) |
@@ -7,17 +7,112 @@ |
#include "vm/flow_graph_compiler.h" |
#include "vm/locations.h" |
+#include "vm/stub_code.h" |
#define __ compiler->assembler()-> |
namespace dart { |
+DECLARE_FLAG(bool, optimization_counter_threshold); |
+DECLARE_FLAG(bool, trace_functions); |
+// True iff. the arguments to a call will be properly pushed and can |
+// be popped after the call. |
+template <typename T> static bool VerifyCallComputation(T* comp) { |
+ // Argument values should be consecutive temps. |
+ // |
+ // TODO(kmillikin): implement stack height tracking so we can also assert |
+ // they are on top of the stack. |
+ intptr_t previous = -1; |
+ for (int i = 0; i < comp->ArgumentCount(); ++i) { |
+ Value* val = comp->ArgumentAt(i); |
+ if (!val->IsUse()) return false; |
+ intptr_t current = val->AsUse()->definition()->temp_index(); |
+ if (i != 0) { |
+ if (current != (previous + 1)) return false; |
+ } |
+ previous = current; |
+ } |
+ return true; |
+} |
+ |
+ |
+// Generic summary for call instructions that have all arguments pushed |
+// on the stack and return the result in a fixed register EAX. |
+static LocationSummary* MakeCallSummary() { |
+ LocationSummary* result = new LocationSummary(0, 0); |
+ result->set_out(Location::RegisterLocation(EAX)); |
+ return result; |
+} |
+ |
+ |
void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
- UNIMPLEMENTED(); |
+ computation()->EmitNativeCode(compiler); |
+ __ pushl(locs()->out().reg()); |
} |
+LocationSummary* ReturnInstr::MakeLocationSummary() const { |
+ const intptr_t kNumInputs = 1; |
+ const intptr_t kNumTemps = 1; |
+ LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
+ locs->set_in(0, Location::RegisterLocation(EAX)); |
+ locs->set_temp(0, Location::RequiresRegister()); |
+ return locs; |
+} |
+ |
+ |
+void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ Register result = locs()->in(0).reg(); |
+ Register temp = locs()->temp(0).reg(); |
+ ASSERT(result == EAX); |
+ if (!compiler->is_optimizing()) { |
+ // Count only in unoptimized code. |
+ // TODO(srdjan): Replace the counting code with a type feedback |
+ // collection and counting stub. |
+ const Function& function = |
+ Function::ZoneHandle(compiler->parsed_function().function().raw()); |
+ __ LoadObject(temp, function); |
+ __ incl(FieldAddress(temp, Function::usage_counter_offset())); |
+ if (CodeGenerator::CanOptimize()) { |
+ // Do not optimize if usage count must be reported. |
+ __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), |
+ Immediate(FLAG_optimization_counter_threshold)); |
+ Label not_yet_hot; |
+ __ j(LESS_EQUAL, ¬_yet_hot, Assembler::kNearJump); |
+ __ pushl(result); // Preserve result. |
+ __ pushl(temp); // Argument for runtime: function to optimize. |
+ __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
+ __ popl(temp); // Remove argument. |
+ __ popl(result); // Restore result. |
+ __ Bind(¬_yet_hot); |
+ } |
+ } |
+ if (FLAG_trace_functions) { |
+ const Function& function = |
+ Function::ZoneHandle(compiler->parsed_function().function().raw()); |
+ __ LoadObject(temp, function); |
+ __ pushl(result); // Preserve result. |
+ __ pushl(temp); |
+ compiler->GenerateCallRuntime(AstNode::kNoId, |
+ 0, |
+ CatchClauseNode::kInvalidTryIndex, |
+ kTraceFunctionExitRuntimeEntry); |
+ __ popl(temp); // Remove argument. |
+ __ popl(result); // Restore result. |
+ } |
+ __ LeaveFrame(); |
+ __ ret(); |
+ // Add a NOP to make return code pattern 5 bytes long for patching |
+ // in breakpoints during debugging. |
+ __ nop(1); |
+ compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
+ cid(), |
+ token_index(), |
+ CatchClauseNode::kInvalidTryIndex); |
+} |
+ |
+ |
LocationSummary* ThrowInstr::MakeLocationSummary() const { |
return NULL; |
} |
@@ -53,7 +148,7 @@ |
} |
-void CurrentContextComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void CurrentContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -63,7 +158,7 @@ |
} |
-void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -73,7 +168,7 @@ |
} |
-void StrictCompareComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void StrictCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -83,58 +178,84 @@ |
} |
-void ClosureCallComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void ClosureCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
LocationSummary* InstanceCallComp::MakeLocationSummary() const { |
- return NULL; |
+ return MakeCallSummary(); |
} |
-void InstanceCallComp::EmitNativeCode(FlowGraphCompiler* compile) { |
- UNIMPLEMENTED(); |
+void InstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ ASSERT(VerifyCallComputation(this)); |
+ compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
+ cid(), |
+ token_index(), |
+ try_index()); |
+ compiler->EmitInstanceCall(cid(), |
+ token_index(), |
+ try_index(), |
+ function_name(), |
+ ArgumentCount(), |
+ argument_names(), |
+ checked_argument_count()); |
} |
LocationSummary* StaticCallComp::MakeLocationSummary() const { |
- return NULL; |
+ return MakeCallSummary(); |
} |
-void StaticCallComp::EmitNativeCode(FlowGraphCompiler* compile) { |
- UNIMPLEMENTED(); |
+void StaticCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ ASSERT(VerifyCallComputation(this)); |
+ compiler->EmitStaticCall(token_index(), |
+ try_index(), |
+ function(), |
+ ArgumentCount(), |
+ argument_names()); |
} |
LocationSummary* LoadLocalComp::MakeLocationSummary() const { |
- return NULL; |
+ return LocationSummary::Make(0, Location::RequiresRegister()); |
} |
-void LoadLocalComp::EmitNativeCode(FlowGraphCompiler* compile) { |
- UNIMPLEMENTED(); |
+void LoadLocalComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ Register result = locs()->out().reg(); |
+ __ movl(result, Address(EBP, local().index() * kWordSize)); |
} |
LocationSummary* StoreLocalComp::MakeLocationSummary() const { |
- return NULL; |
+ return LocationSummary::Make(1, Location::SameAsFirstInput()); |
} |
-void StoreLocalComp::EmitNativeCode(FlowGraphCompiler* compile) { |
- UNIMPLEMENTED(); |
+void StoreLocalComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ Register value = locs()->in(0).reg(); |
+ Register result = locs()->out().reg(); |
+ ASSERT(result == value); // Assert that register assignment is correct. |
+ __ movl(Address(EBP, local().index() * kWordSize), value); |
} |
LocationSummary* ConstantVal::MakeLocationSummary() const { |
- return NULL; |
+ return LocationSummary::Make(0, Location::RequiresRegister()); |
} |
-void ConstantVal::EmitNativeCode(FlowGraphCompiler* compile) { |
- UNIMPLEMENTED(); |
+void ConstantVal::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ Register result = locs()->out().reg(); |
+ if (value().IsSmi()) { |
+ int32_t imm = reinterpret_cast<int32_t>(value().raw()); |
+ __ movl(result, Immediate(imm)); |
+ } else { |
+ __ LoadObject(result, value()); |
+ } |
} |
@@ -143,7 +264,7 @@ |
} |
-void UseVal::EmitNativeCode(FlowGraphCompiler* compile) { |
+void UseVal::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -153,7 +274,7 @@ |
} |
-void AssertAssignableComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void AssertAssignableComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -163,7 +284,7 @@ |
} |
-void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -173,18 +294,42 @@ |
} |
-void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
LocationSummary* NativeCallComp::MakeLocationSummary() const { |
- return NULL; |
+ LocationSummary* locs = new LocationSummary(0, 3); |
+ locs->set_temp(0, Location::RegisterLocation(EAX)); |
+ locs->set_temp(1, Location::RegisterLocation(ECX)); |
+ locs->set_temp(2, Location::RegisterLocation(EDX)); |
+ locs->set_out(Location::RequiresRegister()); |
+ return locs; |
} |
-void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compile) { |
- UNIMPLEMENTED(); |
+void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ ASSERT(locs()->temp(0).reg() == EAX); |
+ ASSERT(locs()->temp(1).reg() == ECX); |
+ ASSERT(locs()->temp(2).reg() == EDX); |
+ Register result = locs()->out().reg(); |
+ // Push the result place holder initialized to NULL. |
+ __ PushObject(Object::ZoneHandle()); |
+ // Pass a pointer to the first argument in EAX. |
+ if (!has_optional_parameters()) { |
+ __ leal(EAX, Address(EBP, (1 + argument_count()) * kWordSize)); |
+ } else { |
+ __ leal(EAX, |
+ Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
+ } |
+ __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
+ __ movl(EDX, Immediate(argument_count())); |
+ compiler->GenerateCall(token_index(), |
+ try_index(), |
+ &StubCode::CallNativeCFunctionLabel(), |
+ PcDescriptors::kOther); |
+ __ popl(result); |
} |
@@ -193,7 +338,7 @@ |
} |
-void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -203,7 +348,7 @@ |
} |
-void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -213,7 +358,7 @@ |
} |
-void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -223,7 +368,7 @@ |
} |
-void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -233,7 +378,7 @@ |
} |
-void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -243,7 +388,7 @@ |
} |
-void LoadStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void LoadStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -253,7 +398,7 @@ |
} |
-void StoreStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void StoreStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -263,7 +408,7 @@ |
} |
-void BooleanNegateComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void BooleanNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -273,7 +418,7 @@ |
} |
-void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -283,7 +428,7 @@ |
} |
-void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -293,7 +438,7 @@ |
} |
-void CreateClosureComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void CreateClosureComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -303,7 +448,7 @@ |
} |
-void AllocateObjectComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void AllocateObjectComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -315,7 +460,7 @@ |
void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
- FlowGraphCompiler* compile) { |
+ FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -325,7 +470,7 @@ |
} |
-void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -335,7 +480,7 @@ |
} |
-void StoreVMFieldComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void StoreVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -346,7 +491,7 @@ |
void InstantiateTypeArgumentsComp::EmitNativeCode( |
- FlowGraphCompiler* compile) { |
+ FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -358,7 +503,7 @@ |
void ExtractConstructorTypeArgumentsComp::EmitNativeCode( |
- FlowGraphCompiler* compile) { |
+ FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -370,7 +515,7 @@ |
void ExtractConstructorInstantiatorComp::EmitNativeCode( |
- FlowGraphCompiler* compile) { |
+ FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -380,7 +525,7 @@ |
} |
-void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -390,7 +535,7 @@ |
} |
-void ChainContextComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void ChainContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -400,7 +545,7 @@ |
} |
-void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
@@ -410,18 +555,34 @@ |
} |
-void CatchEntryComp::EmitNativeCode(FlowGraphCompiler* compile) { |
+void CatchEntryComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
UNIMPLEMENTED(); |
} |
LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
- return NULL; |
+ const intptr_t kNumInputs = 2; |
+ const intptr_t kNumTemps = 0; |
+ LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
+ summary->set_in(0, Location::RequiresRegister()); |
+ summary->set_in(1, Location::RequiresRegister()); |
+ summary->set_out(Location::SameAsFirstInput()); |
+ return summary; |
} |
-void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compile) { |
- UNIMPLEMENTED(); |
+void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ // TODO(srdjan): Remove this code once BinaryOpComp has been implemeneted |
+ // for all intended operations. |
+ Register left = locs()->in(0).reg(); |
+ Register right = locs()->in(1).reg(); |
+ __ pushl(left); |
+ __ pushl(right); |
+ InstanceCallComp* instance_call_comp = instance_call(); |
+ instance_call_comp->EmitNativeCode(compiler); |
+ if (locs()->out().reg() != EAX) { |
+ __ movl(locs()->out().reg(), EAX); |
+ } |
} |