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

Unified Diff: runtime/vm/intermediate_language_arm.cc

Issue 14153004: Implement missing features to run Hello world! on simulated ARM. (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
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('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_arm.cc
===================================================================
--- runtime/vm/intermediate_language_arm.cc (revision 21581)
+++ runtime/vm/intermediate_language_arm.cc (working copy)
@@ -128,11 +128,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(R0));
+ result->set_temp(0, Location::RegisterLocation(R4)); // 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(),
@@ -842,57 +865,345 @@
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();
+ 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: {
+ __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 1));
+ break;
+ }
+ case 8: {
+ __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 2));
+ break;
+ }
+ case 16: {
+ __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 3));
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ __ AddImmediate(index.reg(),
+ FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
+ element_address = Address(array, index.reg(), LSL, 0);
+ }
+
+ 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();
+ 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 = R2;
+ 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 = R3;
+ ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
+ }
+
+ LoadValueCid(compiler, value_cid_reg, value_reg);
+
+ __ ldr(IP, field_cid_operand);
+ __ cmp(value_cid_reg, ShifterOperand(IP));
+ __ b(&ok, EQ);
+ __ ldr(IP, field_nullability_operand);
+ __ cmp(value_cid_reg, ShifterOperand(IP));
+ } else if (value_cid == kNullCid) {
+ // TODO(regis): IP may conflict. Revisit.
+ __ ldr(IP, field_nullability_operand);
+ __ CompareImmediate(IP, value_cid);
+ } else {
+ // TODO(regis): IP may conflict. Revisit.
+ __ ldr(IP, field_cid_operand);
+ __ CompareImmediate(IP, value_cid);
+ }
+ __ b(&ok, EQ);
+
+ __ ldr(IP, field_cid_operand);
+ __ CompareImmediate(IP, kIllegalCid);
+ __ b(fail, NE);
+
+ if (value_cid == kDynamicCid) {
+ __ str(value_cid_reg, field_cid_operand);
+ __ str(value_cid_reg, field_nullability_operand);
+ } else {
+ __ LoadImmediate(IP, value_cid);
+ __ str(IP, field_cid_operand);
+ __ str(IP, 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.
+ __ tst(value_reg, ShifterOperand(kSmiTagMask));
+
+ if (field_cid != kSmiCid) {
+ __ b(fail, EQ);
+ __ LoadClassId(value_cid_reg, value_reg);
+ __ CompareImmediate(value_cid_reg, field_cid);
+ }
+
+ if (field().is_nullable() && (field_cid != kNullCid)) {
+ __ b(&ok, EQ);
+ __ CompareImmediate(value_reg,
+ reinterpret_cast<intptr_t>(Object::null()));
+ }
+
+ if (ok_is_fall_through) {
+ __ b(fail, NE);
+ } else {
+ __ b(&ok, EQ);
+ }
+ } 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);
+
+ __ ldr(IP, FieldAddress(field_reg, Field::guarded_cid_offset()));
+ __ CompareImmediate(IP, kDynamicCid);
+ __ b(&ok, EQ);
+
+ __ 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();
+ Register result = locs()->out().reg();
+ __ LoadObject(result, field());
+ __ LoadFromOffset(kLoadWord, result,
+ 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();
+ 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);
+ }
}
@@ -908,13 +1219,25 @@
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(R1));
+ locs->set_out(Location::RegisterLocation(R0));
+ return locs;
}
void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ // Allocate the array. R2 = length, R1 = element type.
+ ASSERT(locs()->in(0).reg() == R1);
+ __ LoadImmediate(R2, Smi::RawValue(num_elements()));
+ compiler->GenerateCall(token_pos(),
+ &StubCode::AllocateArrayLabel(),
+ PcDescriptors::kOther,
+ locs());
+ ASSERT(locs()->out().reg() == R0);
}
@@ -932,51 +1255,202 @@
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();
+
+ __ LoadFromOffset(kLoadWord, result_reg,
+ 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(R0));
+ locs->set_temp(0, Location::RegisterLocation(R1));
+ locs->set_out(Location::RegisterLocation(R0));
+ return locs;
}
void InstantiateTypeArgumentsInstr::EmitNativeCode(
FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ 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)) {
+ __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+ __ cmp(instantiator_reg, ShifterOperand(IP));
+ __ b(&type_arguments_instantiated, EQ);
+ }
+ // 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;
+ __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp);
+ __ b(&type_arguments_uninstantiated, NE);
+ __ ldr(temp,
+ FieldAddress(instantiator_reg, TypeArguments::length_offset()));
+ __ CompareImmediate(temp, Smi::RawValue(len));
+ __ b(&type_arguments_instantiated, EQ);
+ __ 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)) {
+ __ CompareImmediate(instantiator_reg,
+ reinterpret_cast<intptr_t>(Object::null()));
+ __ b(&type_arguments_instantiated, EQ);
+ }
+ // 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;
+ __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg);
+ __ b(&type_arguments_uninstantiated, NE);
+ __ ldr(temp_reg,
+ FieldAddress(instantiator_reg, TypeArguments::length_offset()));
+ __ CompareImmediate(temp_reg, Smi::RawValue(type_arguments().Length()));
+ __ b(&type_arguments_instantiated, EQ);
+ __ 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;
+ __ CompareImmediate(instantiator_reg,
+ reinterpret_cast<intptr_t>(Object::null()));
+ __ b(&instantiator_not_null, NE);
+ // 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).
+ __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg);
+ __ b(&done, NE);
+ __ ldr(temp_reg,
+ FieldAddress(instantiator_reg, TypeArguments::length_offset()));
+ __ CompareImmediate(temp_reg, Smi::RawValue(type_arguments().Length()));
+ __ b(&done, NE);
+ // 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.
}
@@ -1559,14 +2033,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());
+ __ bkpt(0);
}
@@ -1657,13 +2134,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(), ShifterOperand(CTX));
}
@@ -1750,11 +2228,6 @@
}
-void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
-}
-
-
LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
UNIMPLEMENTED();
return NULL;
@@ -1806,13 +2279,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
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698