| Index: runtime/vm/intermediate_language_mips.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_mips.cc (revision 21951)
|
| +++ runtime/vm/intermediate_language_mips.cc (working copy)
|
| @@ -99,13 +99,11 @@
|
| __ Bind(&stack_ok);
|
| }
|
| #endif
|
| + // This sequence is patched by a debugger breakpoint. There is no need for
|
| + // extra NOP instructions here because the sequence patched in for a
|
| + // breakpoint is shorter than the sequence here.
|
| __ LeaveDartFrame();
|
| __ Ret();
|
| -
|
| - // Generate 2 NOP instructions so that the debugger can patch the return
|
| - // pattern (1 instruction) with a call to the debug stub (3 instructions).
|
| - __ nop();
|
| - __ nop();
|
| compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
|
| Isolate::kNoDeoptId,
|
| token_pos());
|
| @@ -1682,16 +1680,27 @@
|
| case Token::kMUL: {
|
| // Keep left value tagged and untag right value.
|
| const intptr_t value = Smi::Cast(constant).Value();
|
| - if (value == 2) {
|
| - __ sll(result, left, 1);
|
| + if (deopt == NULL) {
|
| + if (value == 2) {
|
| + __ sll(result, left, 1);
|
| + } else {
|
| + __ LoadImmediate(TMP1, value);
|
| + __ mult(left, TMP1);
|
| + __ mflo(result);
|
| + }
|
| } else {
|
| - __ LoadImmediate(TMP1, value);
|
| - __ mult(left, TMP1);
|
| - __ mflo(result);
|
| + if (value == 2) {
|
| + __ sra(TMP1, left, 31); // TMP1 = sign of left.
|
| + __ sll(result, left, 1);
|
| + } else {
|
| + __ LoadImmediate(TMP1, value);
|
| + __ mult(left, TMP1);
|
| + __ mflo(result);
|
| + __ mfhi(TMP1);
|
| + }
|
| + __ sra(TMP2, result, 31);
|
| + __ bne(TMP1, TMP2, deopt);
|
| }
|
| - if (deopt != NULL) {
|
| - UNIMPLEMENTED();
|
| - }
|
| break;
|
| }
|
| case Token::kTRUNCDIV: {
|
| @@ -2379,24 +2388,47 @@
|
|
|
|
|
| LocationSummary* ChainContextInstr::MakeLocationSummary() const {
|
| - UNIMPLEMENTED();
|
| - return NULL;
|
| + return LocationSummary::Make(1,
|
| + Location::NoLocation(),
|
| + LocationSummary::kNoCall);
|
| }
|
|
|
|
|
| void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| - UNIMPLEMENTED();
|
| + 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.
|
| + __ mov(CTX, context_value);
|
| }
|
|
|
|
|
| LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
|
| - UNIMPLEMENTED();
|
| - return NULL;
|
| + const intptr_t kNumInputs = 2;
|
| + const intptr_t kNumTemps = 0;
|
| + LocationSummary* locs =
|
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| + locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
|
| + : Location::RequiresRegister());
|
| + locs->set_in(1, Location::RequiresRegister());
|
| + return locs;
|
| }
|
|
|
|
|
| void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| - UNIMPLEMENTED();
|
| + Register value_reg = locs()->in(0).reg();
|
| + Register dest_reg = locs()->in(1).reg();
|
| +
|
| + if (value()->NeedsStoreBuffer()) {
|
| + __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()),
|
| + value_reg);
|
| + } else {
|
| + __ StoreIntoObjectNoBarrier(
|
| + dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg);
|
| + }
|
| }
|
|
|
|
|
|
|