Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2104)

Unified Diff: runtime/vm/intermediate_language.cc

Issue 10543013: More code for ia32, more shared code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intermediate_language.cc
===================================================================
--- runtime/vm/intermediate_language.cc (revision 8338)
+++ runtime/vm/intermediate_language.cc (working copy)
@@ -6,9 +6,12 @@
#include "vm/bit_vector.h"
#include "vm/flow_graph_builder.h"
+#include "vm/flow_graph_compiler.h"
+#include "vm/locations.h"
#include "vm/object.h"
#include "vm/os.h"
#include "vm/scopes.h"
+#include "vm/stub_code.h"
namespace dart {
@@ -586,5 +589,381 @@
}
+// Shared code generation methods (EmitNativeCode, MakeLocationSummary, and
+// PrepareEntry). Only assembly code that can be shared across all architectures
+// can be used. Machine specific register allocation and code generation
+// is located in intermediate_language_<arch>.cc
+
+// 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;
+}
+
+
+// Truee iff. the v2 is above v1 on stack, or one of them is constant.
+static bool VerifyValues(Value* v1, Value* v2) {
+ ASSERT(v1->IsUse() && v2->IsUse());
+ return (v1->AsUse()->definition()->temp_index() + 1) ==
+ v2->AsUse()->definition()->temp_index();
+}
+
+
+#define __ compiler->assembler()->
+
+void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
+ // Nothing to do.
+}
+
+
+void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
+ __ Bind(compiler->GetBlockLabel(this));
+}
+
+
+void TargetEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
+ __ Bind(compiler->GetBlockLabel(this));
+ if (HasTryIndex()) {
+ compiler->AddExceptionHandler(try_index(),
+ compiler->assembler()->CodeSize());
+ }
+}
+
+
+LocationSummary* ThrowInstr::MakeLocationSummary() const {
+ const int kNumInputs = 0;
+ const int kNumTemps = 0;
+ return new LocationSummary(kNumInputs, kNumTemps);
+}
+
+
+
+void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(exception()->IsUse());
+ compiler->GenerateCallRuntime(cid(),
+ token_index(),
+ try_index(),
+ kThrowRuntimeEntry);
+ __ int3();
Ivan Posva 2012/06/07 06:54:27 How can this be shared code?
+}
+
+
+LocationSummary* ReThrowInstr::MakeLocationSummary() const {
+ const int kNumInputs = 0;
+ const int kNumTemps = 0;
+ return new LocationSummary(kNumInputs, kNumTemps);
+}
+
+
+void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(exception()->IsUse());
+ ASSERT(stack_trace()->IsUse());
+ compiler->GenerateCallRuntime(cid(),
+ token_index(),
+ try_index(),
+ kReThrowRuntimeEntry);
+ __ int3();
Ivan Posva 2012/06/07 06:54:27 ditto!
+}
+
+
+LocationSummary* BranchInstr::MakeLocationSummary() const {
+ const int kNumInputs = 1;
+ const int kNumTemps = 0;
+ LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
+ locs->set_in(0, Location::RequiresRegister());
+ return locs;
+}
+
+
+void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register value = locs()->in(0).reg();
+ __ CompareObject(value, Bool::ZoneHandle(Bool::True()));
+ if (compiler->IsNextBlock(false_successor())) {
+ // If the next block is the false successor we will fall through to it if
+ // comparison with true fails.
+ __ j(EQUAL, compiler->GetBlockLabel(true_successor()));
Ivan Posva 2012/06/07 06:54:27 This is definitely not a portable assembler instru
+ } else {
+ ASSERT(compiler->IsNextBlock(true_successor()));
+ // If the next block is the true successor we negate comparison and fall
+ // through to it.
+ __ j(NOT_EQUAL, compiler->GetBlockLabel(false_successor()));
+ }
+}
+
+
+LocationSummary* CurrentContextComp::MakeLocationSummary() const {
+ return LocationSummary::Make(0, Location::RequiresRegister());
+}
+
+
+void CurrentContextComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ MoveRegister(locs()->out().reg(), CTX);
Ivan Posva 2012/06/07 06:54:27 CTX sounds like a very CPU-specific register to me
+}
+
+
+LocationSummary* StoreContextComp::MakeLocationSummary() const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
+ summary->set_in(0, Location::RegisterLocation(CTX));
+ return summary;
+}
+
+
+void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ // Nothing to do. Context register were loaded by register allocator.
+ ASSERT(locs()->in(0).reg() == CTX);
+}
+
+
+LocationSummary* StrictCompareComp::MakeLocationSummary() const {
+ return LocationSummary::Make(2, Location::SameAsFirstInput());
+}
+
+
+void StrictCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const Bool& bool_true = Bool::ZoneHandle(Bool::True());
+ const Bool& bool_false = Bool::ZoneHandle(Bool::False());
+
+ Register left = locs()->in(0).reg();
+ Register right = locs()->in(1).reg();
+ Register result = locs()->out().reg();
+
+ __ CompareRegisters(left, right);
+ Label load_true, done;
+ if (kind() == Token::kEQ_STRICT) {
+ __ j(EQUAL, &load_true, Assembler::kNearJump);
+ } else {
+ ASSERT(kind() == Token::kNE_STRICT);
+ __ j(NOT_EQUAL, &load_true, Assembler::kNearJump);
+ }
+ __ LoadObject(result, bool_false);
+ __ jmp(&done, Assembler::kNearJump);
+ __ Bind(&load_true);
+ __ LoadObject(result, bool_true);
+ __ Bind(&done);
+}
+
+
+void ClosureCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(VerifyCallComputation(this));
+ // The arguments to the stub include the closure. The arguments
+ // descriptor describes the closure's arguments (and so does not include
+ // the closure).
+ Register temp_reg = locs()->temp(0).reg();
+ int argument_count = ArgumentCount();
+ const Array& arguments_descriptor =
+ CodeGenerator::ArgumentsDescriptor(argument_count - 1,
+ argument_names());
+ __ LoadObject(temp_reg, arguments_descriptor);
+
+ compiler->GenerateCall(token_index(),
+ try_index(),
+ &StubCode::CallClosureFunctionLabel(),
+ PcDescriptors::kOther);
+ __ Drop(argument_count);
+}
+
+
+LocationSummary* InstanceCallComp::MakeLocationSummary() const {
+ return MakeCallSummary();
+}
+
+
+void InstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(VerifyCallComputation(this));
+ compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
+ cid(),
+ token_index(),
+ try_index());
+ compiler->GenerateInstanceCall(cid(),
+ token_index(),
+ try_index(),
+ function_name(),
+ ArgumentCount(),
+ argument_names(),
+ checked_argument_count());
+}
+
+
+LocationSummary* StaticCallComp::MakeLocationSummary() const {
+ return MakeCallSummary();
+}
+
+
+void StaticCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(VerifyCallComputation(this));
+ compiler->GenerateStaticCall(cid(),
+ token_index(),
+ try_index(),
+ function(),
+ ArgumentCount(),
+ argument_names());
+}
+
+
+LocationSummary* UseVal::MakeLocationSummary() const {
+ return NULL;
+}
+
+
+void UseVal::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNIMPLEMENTED();
+}
+
+
+void AssertAssignableComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ compiler->GenerateAssertAssignable(cid(),
+ token_index(),
+ try_index(),
+ dst_type(),
+ dst_name());
+ ASSERT(locs()->in(0).reg() == locs()->out().reg());
+}
+
+
+LocationSummary* AssertBooleanComp::MakeLocationSummary() const {
+ return LocationSummary::Make(1, Location::SameAsFirstInput());
+}
+
+
+LocationSummary* StoreInstanceFieldComp::MakeLocationSummary() const {
+ return LocationSummary::Make(2, Location::RequiresRegister());
+}
+
+
+void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(VerifyValues(instance(), value()));
+ Register instance = locs()->in(0).reg();
+ Register value = locs()->in(1).reg();
+ Register result = locs()->out().reg();
+
+ __ StoreIntoObject(instance, FieldAddress(instance, field().Offset()),
+ value);
+ // TODO(fschneider): Consider eliminating this move by specifying a
+ // SameAsSecondInput for the result.
+ __ MoveRegister(result, value);
+}
+
+
+LocationSummary* StoreStaticFieldComp::MakeLocationSummary() const {
+ LocationSummary* locs = new LocationSummary(1, 1);
+ locs->set_in(0, Location::RequiresRegister());
+ locs->set_temp(0, Location::RequiresRegister());
+ locs->set_out(Location::SameAsFirstInput());
+ return locs;
+}
+
+
+void StoreStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register value = locs()->in(0).reg();
+ Register temp = locs()->temp(0).reg();
+ ASSERT(locs()->out().reg() == value);
+
+ __ LoadObject(temp, field());
+ __ StoreIntoObject(temp, FieldAddress(temp, Field::value_offset()), value);
+}
+
+
+LocationSummary* BooleanNegateComp::MakeLocationSummary() const {
+ return LocationSummary::Make(1, Location::RequiresRegister());
+}
+
+
+void BooleanNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register value = locs()->in(0).reg();
+ Register result = locs()->out().reg();
+
+ const Bool& bool_true = Bool::ZoneHandle(Bool::True());
+ const Bool& bool_false = Bool::ZoneHandle(Bool::False());
+ Label done;
+ __ LoadObject(result, bool_true);
+ __ CompareRegisters(result, value);
+ __ j(NOT_EQUAL, &done, Assembler::kNearJump);
+ __ LoadObject(result, bool_false);
+ __ Bind(&done);
+}
+
+
+LocationSummary* ChainContextComp::MakeLocationSummary() const {
+ return LocationSummary::Make(1, Location::NoLocation());
+}
+
+
+void ChainContextComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register context_value = locs()->in(0).reg();
+
+ // Chain the new context in context_value to its parent in CTX.
+ __ StoreIntoObject(context_value,
+ FieldAddress(context_value, Context::parent_offset()),
+ CTX);
+ // Set new context as current context.
+ __ MoveRegister(CTX, context_value);
+}
+
+
+LocationSummary* StoreVMFieldComp::MakeLocationSummary() const {
+ return LocationSummary::Make(2, Location::SameAsFirstInput());
+}
+
+
+void StoreVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register value_reg = locs()->in(0).reg();
+ Register dest_reg = locs()->in(1).reg();
+ ASSERT(value_reg == locs()->out().reg());
+
+ __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()),
+ value_reg);
+}
+
+
+LocationSummary* AllocateObjectComp::MakeLocationSummary() const {
+ return MakeCallSummary();
+}
+
+
+void AllocateObjectComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const Class& cls = Class::ZoneHandle(constructor().owner());
+ const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
+ const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
+ compiler->GenerateCall(token_index(),
+ try_index(),
+ &label,
+ PcDescriptors::kOther);
+ __ Drop(arguments().length()); // Discard arguments.
+}
+
+
+LocationSummary* CreateClosureComp::MakeLocationSummary() const {
+ return MakeCallSummary();
+}
+
+
+void CreateClosureComp::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const Function& closure_function = function();
+ const Code& stub = Code::Handle(
+ StubCode::GetAllocationStubForClosure(closure_function));
+ const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint());
+ compiler->GenerateCall(token_index(), try_index(), &label,
+ PcDescriptors::kOther);
+ __ Drop(2); // Discard type arguments and receiver.
+}
+
+#undef __
+
} // namespace dart
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698