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

Unified Diff: runtime/vm/intermediate_language_mips.cc

Issue 14246039: Implements features to run "Hello, world!" on simulated MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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
Index: runtime/vm/intermediate_language_mips.cc
===================================================================
--- runtime/vm/intermediate_language_mips.cc (revision 21753)
+++ runtime/vm/intermediate_language_mips.cc (working copy)
@@ -46,6 +46,7 @@
void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
// where PushArgument is handled by BindInstr::EmitNativeCode.
+ __ Msg("PushArgumentInstr");
if (compiler->is_optimizing()) {
Location value = locs()->in(0);
if (value.IsRegister()) {
@@ -75,6 +76,7 @@
// The entry needs to be patchable, no inlined objects are allowed in the area
// that will be overwritten by the patch instructions: a branch macro sequence.
void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("ReturnInstr");
Register result = locs()->in(0).reg();
ASSERT(result == V0);
#if defined(DEBUG)
@@ -85,6 +87,7 @@
if (!compiler->HasFinally()) {
Label stack_ok;
__ Comment("Stack Check");
+ __ Msg("Stack Check");
const intptr_t fp_sp_dist =
(kFirstLocalSlotIndex + 1 - compiler->StackSize()) * kWordSize;
ASSERT(fp_sp_dist <= 0);
@@ -134,11 +137,34 @@
LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 0;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* result =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+ result->set_out(Location::RegisterLocation(V0));
+ result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor.
+ return result;
}
+void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ // The arguments to the stub include the closure, as does the arguments
+ // descriptor.
+ Register temp_reg = locs()->temp(0).reg();
+ int argument_count = ArgumentCount();
+ const Array& arguments_descriptor =
+ Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
+ argument_names()));
+ __ LoadObject(temp_reg, arguments_descriptor);
+ compiler->GenerateDartCall(deopt_id(),
+ token_pos(),
+ &StubCode::CallClosureFunctionLabel(),
+ PcDescriptors::kOther,
+ locs());
+ __ Drop(argument_count);
+}
+
+
LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
return LocationSummary::Make(0,
Location::RequiresRegister(),
@@ -147,6 +173,7 @@
void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("LoadLocalInstr");
Register result = locs()->out().reg();
__ lw(result, Address(FP, local().index() * kWordSize));
}
@@ -160,6 +187,7 @@
void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("StoreLocalInstr");
Register value = locs()->in(0).reg();
Register result = locs()->out().reg();
ASSERT(result == value); // Assert that register assignment is correct.
@@ -177,6 +205,7 @@
void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// The register allocator drops constant definitions that have no uses.
if (!locs()->out().IsInvalid()) {
+ __ Msg("ConstantInstr");
Register result = locs()->out().reg();
__ LoadObject(result, value());
}
@@ -234,6 +263,7 @@
Register obj = locs()->in(0).reg();
Register result = locs()->out().reg();
+ __ Msg("AssertBooleanInstr");
EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
ASSERT(obj == result);
}
@@ -324,6 +354,7 @@
Token::Kind kind,
LocationSummary* locs,
const ICData& original_ic_data) {
+ __ Msg("EmitEqualityAsInstanceCall");
if (!compiler->is_optimizing()) {
compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
deopt_id,
@@ -411,6 +442,7 @@
Register value_cid_reg,
Register value_reg,
Label* value_is_smi = NULL) {
+ __ Msg("LoadValueCid");
Label done;
if (value_is_smi == NULL) {
__ LoadImmediate(value_cid_reg, kSmiCid);
@@ -470,6 +502,7 @@
const LocationSummary& locs,
Token::Kind kind,
BranchInstr* branch) {
+ __ Msg("EmitSmiComparisonOp");
Location left = locs.in(0);
Location right = locs.in(1);
ASSERT(!left.IsConstant() || !right.IsConstant());
@@ -577,6 +610,7 @@
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
+ __ Msg("EqualityCompareInstr");
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
if (receiver_class_id() == kSmiCid) {
// Deoptimizes if both arguments not Smi.
@@ -666,6 +700,7 @@
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("RelationalOpInstr");
if (operands_class_id() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
return;
@@ -737,6 +772,7 @@
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
+ __ Msg("RelationalOpInstr");
if (operands_class_id() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
@@ -769,6 +805,7 @@
void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("NativeCallInstr");
ASSERT(locs()->temp(0).reg() == A1);
ASSERT(locs()->temp(1).reg() == A2);
ASSERT(locs()->temp(2).reg() == T5);
@@ -853,57 +890,349 @@
LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 3;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* locs =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ locs->set_in(0, Location::RequiresRegister());
+ // The smi index is either untagged (element size == 1), or it is left smi
+ // tagged (for all element sizes > 1).
+ // TODO(regis): Revisit and see if the index can be immediate.
+ locs->set_in(1, Location::WritableRegister());
+ switch (class_id()) {
+ case kArrayCid:
+ locs->set_in(2, ShouldEmitStoreBarrier()
+ ? Location::WritableRegister()
+ : Location::RegisterOrConstant(value()));
+ break;
+ case kExternalTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ case kTypedDataInt32ArrayCid:
+ case kTypedDataUint32ArrayCid:
+ case kTypedDataFloat32ArrayCid:
+ case kTypedDataFloat64ArrayCid:
+ case kTypedDataFloat32x4ArrayCid:
+ UNIMPLEMENTED();
+ break;
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ return locs;
}
void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ __ Msg("StoreIndexedInstr");
+ Register array = locs()->in(0).reg();
+ Location index = locs()->in(1);
+
+ Address element_address(kNoRegister, 0);
+ if (IsExternal()) {
+ UNIMPLEMENTED();
+ } else {
+ ASSERT(this->array()->definition()->representation() == kTagged);
+ ASSERT(index.IsRegister()); // TODO(regis): Revisit.
+ // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
+ // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
+ // index is expected to be untagged before accessing.
+ ASSERT(kSmiTagShift == 1);
+ switch (index_scale()) {
+ case 1: {
+ __ SmiUntag(index.reg());
+ break;
+ }
+ case 2: {
+ break;
+ }
+ case 4: {
+ __ sll(index.reg(), index.reg(), 1);
+ break;
+ }
+ case 8: {
+ __ sll(index.reg(), index.reg(), 2);
+ break;
+ }
+ case 16: {
+ __ sll(index.reg(), index.reg(), 3);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ __ AddImmediate(index.reg(),
+ FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
+ __ addu(TMP1, array, index.reg());
+ element_address = Address(TMP1);
+ }
+
+ switch (class_id()) {
+ case kArrayCid:
+ if (ShouldEmitStoreBarrier()) {
+ Register value = locs()->in(2).reg();
+ __ StoreIntoObject(array, element_address, value);
+ } else if (locs()->in(2).IsConstant()) {
+ const Object& constant = locs()->in(2).constant();
+ __ StoreIntoObjectNoBarrier(array, element_address, constant);
+ } else {
+ Register value = locs()->in(2).reg();
+ __ StoreIntoObjectNoBarrier(array, element_address, value);
+ }
+ break;
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ case kTypedDataInt32ArrayCid:
+ case kTypedDataUint32ArrayCid:
+ case kTypedDataFloat32ArrayCid:
+ case kTypedDataFloat64ArrayCid:
+ case kTypedDataFloat32x4ArrayCid:
+ UNIMPLEMENTED();
+ break;
+ default:
+ UNREACHABLE();
+ }
}
LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ if ((value()->Type()->ToCid() == kDynamicCid) &&
+ (field().guarded_cid() != kSmiCid)) {
+ summary->AddTemp(Location::RequiresRegister());
+ }
+ if (field().guarded_cid() == kIllegalCid) {
+ summary->AddTemp(Location::RequiresRegister());
+ }
+ return summary;
}
void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ __ Msg("GuardFieldInstr");
+ const intptr_t field_cid = field().guarded_cid();
+ const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
+
+ if (field_cid == kDynamicCid) {
+ ASSERT(!compiler->is_optimizing());
+ return; // Nothing to emit.
+ }
+
+ const intptr_t value_cid = value()->Type()->ToCid();
+
+ Register value_reg = locs()->in(0).reg();
+
+ Register value_cid_reg = ((value_cid == kDynamicCid) &&
+ (field_cid != kSmiCid)) ? locs()->temp(0).reg() : kNoRegister;
+
+ Register field_reg = (field_cid == kIllegalCid) ?
+ locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
+
+ Label ok, fail_label;
+
+ Label* deopt = compiler->is_optimizing() ?
+ compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
+
+ Label* fail = (deopt != NULL) ? deopt : &fail_label;
+
+ const bool ok_is_fall_through = (deopt != NULL);
+
+ if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
+ if (!compiler->is_optimizing()) {
+ // Currently we can't have different location summaries for optimized
+ // and non-optimized code. So instead we manually pick up a register
+ // that is known to be free because we know how non-optimizing compiler
+ // allocates registers.
+ field_reg = A0;
+ ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
+ }
+
+ __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
+
+ FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
+ FieldAddress field_nullability_operand(
+ field_reg, Field::is_nullable_offset());
+
+ if (value_cid == kDynamicCid) {
+ if (value_cid_reg == kNoRegister) {
+ ASSERT(!compiler->is_optimizing());
+ value_cid_reg = A1;
+ ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
+ }
+
+ LoadValueCid(compiler, value_cid_reg, value_reg);
+
+ __ lw(TMP1, field_cid_operand);
+ __ beq(value_cid_reg, TMP1, &ok);
+ __ lw(TMP1, field_nullability_operand);
+ __ subu(CMPRES, value_cid_reg, TMP1);
+ } else if (value_cid == kNullCid) {
+ // TODO(regis): TMP1 may conflict. Revisit.
+ __ lw(TMP1, field_nullability_operand);
+ __ LoadImmediate(TMP2, value_cid);
+ __ subu(CMPRES, TMP1, TMP2);
+ } else {
+ // TODO(regis): TMP1 may conflict. Revisit.
+ __ lw(TMP1, field_cid_operand);
+ __ LoadImmediate(TMP2, value_cid);
+ __ subu(CMPRES, TMP1, TMP2);
+ }
+ __ beq(CMPRES, ZR, &ok);
+
+ __ lw(TMP1, field_cid_operand);
+ __ BranchNotEqual(TMP1, kIllegalCid, fail);
+
+ if (value_cid == kDynamicCid) {
+ __ sw(value_cid_reg, field_cid_operand);
+ __ sw(value_cid_reg, field_nullability_operand);
+ } else {
+ __ LoadImmediate(TMP1, value_cid);
+ __ sw(TMP1, field_cid_operand);
+ __ sw(TMP1, field_nullability_operand);
+ }
+
+ if (!ok_is_fall_through) {
+ __ b(&ok);
+ }
+ } else {
+ if (value_cid == kDynamicCid) {
+ // Field's guarded class id is fixed by value's class id is not known.
+ __ andi(CMPRES, value_reg, Immediate(kSmiTagMask));
+
+ if (field_cid != kSmiCid) {
+ __ beq(CMPRES, ZR, fail);
+ __ LoadClassId(value_cid_reg, value_reg);
+ __ LoadImmediate(TMP1, field_cid);
+ __ subu(CMPRES, value_cid_reg, TMP1);
+ }
+
+ if (field().is_nullable() && (field_cid != kNullCid)) {
+ __ beq(CMPRES, ZR, &ok);
+ __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null()));
+ __ subu(CMPRES, value_reg, TMP1);
+ }
+
+ if (ok_is_fall_through) {
+ __ bne(CMPRES, ZR, fail);
+ } else {
+ __ beq(CMPRES, ZR, &ok);
+ }
+ } else {
+ // Both value's and field's class id is known.
+ if ((value_cid != field_cid) && (value_cid != nullability)) {
+ if (ok_is_fall_through) {
+ __ b(fail);
+ }
+ } else {
+ // Nothing to emit.
+ ASSERT(!compiler->is_optimizing());
+ return;
+ }
+ }
+ }
+
+ if (deopt == NULL) {
+ ASSERT(!compiler->is_optimizing());
+ __ Bind(fail);
+
+ __ lw(TMP1, FieldAddress(field_reg, Field::guarded_cid_offset()));
+ __ BranchEqual(TMP1, kDynamicCid, &ok);
+
+ __ Push(field_reg);
+ __ Push(value_reg);
+ __ CallRuntime(kUpdateFieldCidRuntimeEntry);
+ __ Drop(2); // Drop the field and the value.
+ }
+
+ __ Bind(&ok);
}
LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t num_temps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, ShouldEmitStoreBarrier()
+ ? Location::WritableRegister()
+ : Location::RegisterOrConstant(value()));
+ return summary;
}
void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Register instance_reg = locs()->in(0).reg();
+ if (ShouldEmitStoreBarrier()) {
+ Register value_reg = locs()->in(1).reg();
+ __ StoreIntoObject(instance_reg,
+ FieldAddress(instance_reg, field().Offset()),
+ value_reg,
+ CanValueBeSmi());
+ } else {
+ if (locs()->in(1).IsConstant()) {
+ __ StoreIntoObjectNoBarrier(
+ instance_reg,
+ FieldAddress(instance_reg, field().Offset()),
+ locs()->in(1).constant());
+ } else {
+ Register value_reg = locs()->in(1).reg();
+ __ StoreIntoObjectNoBarrier(instance_reg,
+ FieldAddress(instance_reg, field().Offset()), value_reg);
+ }
+ }
}
LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ return LocationSummary::Make(0,
+ Location::RequiresRegister(),
+ LocationSummary::kNoCall);
}
void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ __ Msg("LoadStaticFieldInstr");
+ Register result = locs()->out().reg();
+ __ LoadObject(result, field());
+ __ lw(result, Address(result, Field::value_offset() - kHeapObjectTag));
}
LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall);
+ locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
+ : Location::RequiresRegister());
+ locs->set_temp(0, Location::RequiresRegister());
+ return locs;
}
void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ __ Msg("StoreStaticFieldInstr");
+ Register value = locs()->in(0).reg();
+ Register temp = locs()->temp(0).reg();
+
+ __ LoadObject(temp, field());
+ if (this->value()->NeedsStoreBuffer()) {
+ __ StoreIntoObject(temp,
+ FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi());
+ } else {
+ __ StoreIntoObjectNoBarrier(
+ temp, FieldAddress(temp, Field::value_offset()), value);
+ }
}
@@ -919,13 +1248,26 @@
LocationSummary* CreateArrayInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* locs =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+ locs->set_in(0, Location::RegisterLocation(A0));
+ locs->set_out(Location::RegisterLocation(V0));
+ return locs;
}
void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ __ Msg("CreateArrayInstr");
+ // Allocate the array. A1 = length, A0 = element type.
+ ASSERT(locs()->in(0).reg() == A0);
+ __ LoadImmediate(A1, Smi::RawValue(num_elements()));
+ compiler->GenerateCall(token_pos(),
+ &StubCode::AllocateArrayLabel(),
+ PcDescriptors::kOther,
+ locs());
+ ASSERT(locs()->out().reg() == V0);
}
@@ -943,51 +1285,198 @@
LocationSummary* LoadFieldInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ return LocationSummary::Make(1,
+ Location::RequiresRegister(),
+ LocationSummary::kNoCall);
}
void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Register instance_reg = locs()->in(0).reg();
+ Register result_reg = locs()->out().reg();
+
+ __ lw(result_reg, Address(instance_reg, offset_in_bytes() - kHeapObjectTag));
}
LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* locs =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+ locs->set_in(0, Location::RegisterLocation(T0));
+ locs->set_temp(0, Location::RegisterLocation(T1));
+ locs->set_out(Location::RegisterLocation(T0));
+ return locs;
}
void InstantiateTypeArgumentsInstr::EmitNativeCode(
FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ __ Msg("InstantiateTypeArgumentsInstr");
+ Register instantiator_reg = locs()->in(0).reg();
+ Register temp = locs()->temp(0).reg();
+ Register result_reg = locs()->out().reg();
+
+ // 'instantiator_reg' is the instantiator AbstractTypeArguments object
+ // (or null).
+ // If the instantiator is null and if the type argument vector
+ // instantiated from null becomes a vector of dynamic, then use null as
+ // the type arguments.
+ Label type_arguments_instantiated;
+ const intptr_t len = type_arguments().Length();
+ if (type_arguments().IsRawInstantiatedRaw(len)) {
+ __ BranchEqual(instantiator_reg, reinterpret_cast<intptr_t>(Object::null()),
+ &type_arguments_instantiated);
+ }
+ // Instantiate non-null type arguments.
+ if (type_arguments().IsUninstantiatedIdentity()) {
+ // Check if the instantiator type argument vector is a TypeArguments of a
+ // matching length and, if so, use it as the instantiated type_arguments.
+ // No need to check the instantiator ('instantiator_reg') for null here,
+ // because a null instantiator will have the wrong class (Null instead of
+ // TypeArguments).
+ Label type_arguments_uninstantiated;
+ __ LoadClassId(temp, instantiator_reg);
+ __ BranchNotEqual(temp, kTypeArgumentsCid, &type_arguments_uninstantiated);
+ __ lw(temp, FieldAddress(instantiator_reg, TypeArguments::length_offset()));
+ __ BranchEqual(temp, Smi::RawValue(len), &type_arguments_instantiated);
+ __ Bind(&type_arguments_uninstantiated);
+ }
+ // A runtime call to instantiate the type arguments is required.
+ __ PushObject(Object::ZoneHandle()); // Make room for the result.
+ __ PushObject(type_arguments());
+ __ Push(instantiator_reg); // Push instantiator type arguments.
+ compiler->GenerateCallRuntime(token_pos(),
+ deopt_id(),
+ kInstantiateTypeArgumentsRuntimeEntry,
+ locs());
+ __ Drop(2); // Drop instantiator and uninstantiated type arguments.
+ __ Pop(result_reg); // Pop instantiated type arguments.
+ __ Bind(&type_arguments_instantiated);
+ ASSERT(instantiator_reg == result_reg);
+ // 'result_reg': Instantiated type arguments.
}
LocationSummary*
ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* locs =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ locs->set_in(0, Location::RequiresRegister());
+ locs->set_out(Location::SameAsFirstInput());
+ locs->set_temp(0, Location::RequiresRegister());
+ return locs;
}
void ExtractConstructorTypeArgumentsInstr::EmitNativeCode(
FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Register instantiator_reg = locs()->in(0).reg();
+ Register result_reg = locs()->out().reg();
+ ASSERT(instantiator_reg == result_reg);
+ Register temp_reg = locs()->temp(0).reg();
+
+ // instantiator_reg is the instantiator type argument vector, i.e. an
+ // AbstractTypeArguments object (or null).
+ // If the instantiator is null and if the type argument vector
+ // instantiated from null becomes a vector of dynamic, then use null as
+ // the type arguments.
+ Label type_arguments_instantiated;
+ const intptr_t len = type_arguments().Length();
+ if (type_arguments().IsRawInstantiatedRaw(len)) {
+ __ BranchEqual(instantiator_reg, reinterpret_cast<intptr_t>(Object::null()),
+ &type_arguments_instantiated);
+ }
+ // Instantiate non-null type arguments.
+ if (type_arguments().IsUninstantiatedIdentity()) {
+ // Check if the instantiator type argument vector is a TypeArguments of a
+ // matching length and, if so, use it as the instantiated type_arguments.
+ // No need to check instantiator_reg for null here, because a null
+ // instantiator will have the wrong class (Null instead of TypeArguments).
+ Label type_arguments_uninstantiated;
+ __ LoadClassId(temp_reg, instantiator_reg);
+ __ BranchNotEqual(temp_reg, kTypeArgumentsCid,
+ &type_arguments_uninstantiated);
+ __ lw(temp_reg,
+ FieldAddress(instantiator_reg, TypeArguments::length_offset()));
+ __ BranchEqual(temp_reg, Smi::RawValue(type_arguments().Length()),
+ &type_arguments_instantiated);
+ __ Bind(&type_arguments_uninstantiated);
+ }
+ // In the non-factory case, we rely on the allocation stub to
+ // instantiate the type arguments.
+ __ LoadObject(result_reg, type_arguments());
+ // result_reg: uninstantiated type arguments.
+ __ Bind(&type_arguments_instantiated);
+ // result_reg: uninstantiated or instantiated type arguments.
}
LocationSummary*
ExtractConstructorInstantiatorInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* locs =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ locs->set_in(0, Location::RequiresRegister());
+ locs->set_out(Location::SameAsFirstInput());
+ locs->set_temp(0, Location::RequiresRegister());
+ return locs;
}
void ExtractConstructorInstantiatorInstr::EmitNativeCode(
FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Register instantiator_reg = locs()->in(0).reg();
+ ASSERT(locs()->out().reg() == instantiator_reg);
+ Register temp_reg = locs()->temp(0).reg();
+
+ // instantiator_reg is the instantiator AbstractTypeArguments object
+ // (or null). If the instantiator is null and if the type argument vector
+ // instantiated from null becomes a vector of dynamic, then use null as
+ // the type arguments and do not pass the instantiator.
+ Label done;
+ const intptr_t len = type_arguments().Length();
+ if (type_arguments().IsRawInstantiatedRaw(len)) {
+ Label instantiator_not_null;
+ __ BranchNotEqual(instantiator_reg,
+ reinterpret_cast<intptr_t>(Object::null()), &instantiator_not_null);
+ // Null was used in VisitExtractConstructorTypeArguments as the
+ // instantiated type arguments, no proper instantiator needed.
+ __ LoadImmediate(instantiator_reg,
+ Smi::RawValue(StubCode::kNoInstantiator));
+ __ b(&done);
+ __ Bind(&instantiator_not_null);
+ }
+ // Instantiate non-null type arguments.
+ if (type_arguments().IsUninstantiatedIdentity()) {
+ // TODO(regis): The following emitted code is duplicated in
+ // VisitExtractConstructorTypeArguments above. The reason is that the code
+ // is split between two computations, so that each one produces a
+ // single value, rather than producing a pair of values.
+ // If this becomes an issue, we should expose these tests at the IL level.
+
+ // Check if the instantiator type argument vector is a TypeArguments of a
+ // matching length and, if so, use it as the instantiated type_arguments.
+ // No need to check the instantiator ('instantiator_reg') for null here,
+ // because a null instantiator will have the wrong class (Null instead of
+ // TypeArguments).
+ __ LoadClassId(temp_reg, instantiator_reg);
+ __ BranchNotEqual(temp_reg, kTypeArgumentsCid, &done);
+ __ lw(temp_reg,
+ FieldAddress(instantiator_reg, TypeArguments::length_offset()));
+ __ BranchNotEqual(temp_reg, Smi::RawValue(type_arguments().Length()),
+ &done);
+ // The instantiator was used in VisitExtractConstructorTypeArguments as the
+ // instantiated type arguments, no proper instantiator needed.
+ __ LoadImmediate(instantiator_reg,
+ Smi::RawValue(StubCode::kNoInstantiator));
+ }
+ __ Bind(&done);
+ // instantiator_reg: instantiator or kNoInstantiator.
}
@@ -1041,6 +1530,7 @@
: instruction_(instruction) { }
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("CheckStackOverflowSlowPath");
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
compiler->SaveLiveRegisters(instruction_->locs());
@@ -1063,6 +1553,7 @@
void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("CheckStackOverflowInstr");
CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
compiler->AddSlowPathCode(slow_path);
@@ -1095,6 +1586,7 @@
void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("BinarySmiOpInstr");
if (op_kind() == Token::kSHL) {
UNIMPLEMENTED();
return;
@@ -1429,6 +1921,7 @@
void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("PolymorphicInstanceCallInstr");
Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
kDeoptPolymorphicInstanceCallTestFail);
if (ic_data().NumberOfChecks() == 0) {
@@ -1448,7 +1941,7 @@
return;
}
- // Load receiver into R0.
+ // Load receiver into T0.
__ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize));
LoadValueCid(compiler, T2, T0,
@@ -1472,6 +1965,7 @@
void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("BranchInstr");
comparison()->EmitBranchCode(compiler, this);
}
@@ -1498,6 +1992,7 @@
void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("CheckSmiInstr");
Register value = locs()->in(0).reg();
Label* deopt = compiler->AddDeoptStub(deopt_id(),
kDeoptCheckSmi);
@@ -1573,14 +2068,17 @@
LocationSummary* ThrowInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ return new LocationSummary(0, 0, LocationSummary::kCall);
}
void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ compiler->GenerateCallRuntime(token_pos(),
+ deopt_id(),
+ kThrowRuntimeEntry,
+ locs());
+ __ break_(0);
}
@@ -1601,6 +2099,7 @@
void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("GotoInstr");
// Add deoptimization descriptor for deoptimizing instructions
// that may be inserted before this instruction.
if (!compiler->is_optimizing()) {
@@ -1639,6 +2138,7 @@
void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
bool value) {
+ __ Msg("ControlInstruction::EmitBranchOnValue");
if (value && !compiler->CanFallThroughTo(true_successor())) {
__ b(compiler->GetJumpLabel(true_successor()));
} else if (!value && !compiler->CanFallThroughTo(false_successor())) {
@@ -1650,6 +2150,7 @@
// The comparison result is in CMPRES.
void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
Condition true_condition) {
+ __ Msg("ControlInstruction::EmitBranchOnCondition");
if (compiler->CanFallThroughTo(false_successor())) {
// If the next block is the false successor we will fall through to it.
Label* label = compiler->GetJumpLabel(true_successor());
@@ -1689,13 +2190,14 @@
LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ return LocationSummary::Make(0,
+ Location::RequiresRegister(),
+ LocationSummary::kNoCall);
}
void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ __ mov(locs()->out().reg(), CTX);
}
@@ -1713,6 +2215,7 @@
// Special code for numbers (compare values instead of references.)
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("StrictCompareInstr");
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
Location left = locs()->in(0);
Location right = locs()->in(1);
@@ -1756,6 +2259,7 @@
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
+ __ Msg("StrictCompareInstr::EmitBranchCode");
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
Location left = locs()->in(0);
Location right = locs()->in(1);
@@ -1786,11 +2290,6 @@
}
-void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
-}
-
-
LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
UNIMPLEMENTED();
return NULL;
@@ -1830,6 +2329,7 @@
void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Msg("AllocateObjectInstr");
const Class& cls = Class::ZoneHandle(constructor().Owner());
const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
@@ -1842,13 +2342,21 @@
LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ return MakeCallSummary();
}
void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ const Function& closure_function = function();
+ ASSERT(!closure_function.IsImplicitStaticClosureFunction());
+ const Code& stub = Code::Handle(
+ StubCode::GetAllocationStubForClosure(closure_function));
+ const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint());
+ compiler->GenerateCall(token_pos(),
+ &label,
+ PcDescriptors::kOther,
+ locs());
+ __ Drop(2); // Discard type arguments and receiver.
}
} // namespace dart

Powered by Google App Engine
This is Rietveld 408576698