Index: src/arm/codegen-arm.cc |
=================================================================== |
--- src/arm/codegen-arm.cc (revision 3716) |
+++ src/arm/codegen-arm.cc (working copy) |
@@ -1,4 +1,4 @@ |
-// Copyright 2006-2009 the V8 project authors. All rights reserved. |
+// Copyright 2010 the V8 project authors. All rights reserved. |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
// met: |
@@ -605,14 +605,19 @@ |
} |
-Reference::Reference(CodeGenerator* cgen, Expression* expression) |
- : cgen_(cgen), expression_(expression), type_(ILLEGAL) { |
+Reference::Reference(CodeGenerator* cgen, |
+ Expression* expression, |
+ bool persist_after_get) |
+ : cgen_(cgen), |
+ expression_(expression), |
+ type_(ILLEGAL), |
+ persist_after_get_(persist_after_get) { |
cgen->LoadReference(this); |
} |
Reference::~Reference() { |
- cgen_->UnloadReference(this); |
+ ASSERT(is_unloaded() || is_illegal()); |
} |
@@ -661,6 +666,7 @@ |
frame_->Drop(size); |
frame_->EmitPush(r0); |
} |
+ ref->set_unloaded(); |
} |
@@ -1244,8 +1250,6 @@ |
Reference target(this, node->proxy()); |
LoadAndSpill(val); |
target.SetValue(NOT_CONST_INIT); |
- // The reference is removed from the stack (preserving TOS) when |
- // it goes out of scope. |
} |
// Get rid of the assigned value (declarations are statements). |
frame_->Drop(); |
@@ -1932,25 +1936,17 @@ |
if (each.size() > 0) { |
__ ldr(r0, frame_->ElementAt(each.size())); |
frame_->EmitPush(r0); |
+ each.SetValue(NOT_CONST_INIT); |
+ frame_->Drop(2); |
+ } else { |
+ // If the reference was to a slot we rely on the convenient property |
+ // that it doesn't matter whether a value (eg, r3 pushed above) is |
+ // right on top of or right underneath a zero-sized reference. |
+ each.SetValue(NOT_CONST_INIT); |
+ frame_->Drop(); |
} |
- // If the reference was to a slot we rely on the convenient property |
- // that it doesn't matter whether a value (eg, r3 pushed above) is |
- // right on top of or right underneath a zero-sized reference. |
- each.SetValue(NOT_CONST_INIT); |
- if (each.size() > 0) { |
- // It's safe to pop the value lying on top of the reference before |
- // unloading the reference itself (which preserves the top of stack, |
- // ie, now the topmost value of the non-zero sized reference), since |
- // we will discard the top of stack after unloading the reference |
- // anyway. |
- frame_->EmitPop(r0); |
- } |
} |
} |
- // Discard the i'th entry pushed above or else the remainder of the |
- // reference, whichever is currently on top of the stack. |
- frame_->Drop(); |
- |
// Body. |
CheckStack(); // TODO(1222600): ignore if body contains calls. |
VisitAndSpill(node->body()); |
@@ -2844,7 +2840,7 @@ |
VirtualFrame::SpilledScope spilled_scope; |
Comment cmnt(masm_, "[ Assignment"); |
- { Reference target(this, node->target()); |
+ { Reference target(this, node->target(), node->is_compound()); |
if (target.is_illegal()) { |
// Fool the virtual frame into thinking that we left the assignment's |
// value on the frame. |
@@ -2859,8 +2855,7 @@ |
node->op() == Token::INIT_CONST) { |
LoadAndSpill(node->value()); |
- } else { |
- // +=, *= and similar binary assignments. |
+ } else { // Assignment is a compound assignment. |
// Get the old value of the lhs. |
target.GetValueAndSpill(); |
Literal* literal = node->value()->AsLiteral(); |
@@ -2881,13 +2876,12 @@ |
frame_->EmitPush(r0); |
} |
} |
- |
Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
if (var != NULL && |
(var->mode() == Variable::CONST) && |
node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { |
// Assignment ignored - leave the value on the stack. |
- |
+ UnloadReference(&target); |
} else { |
CodeForSourcePosition(node->position()); |
if (node->op() == Token::INIT_CONST) { |
@@ -3097,16 +3091,20 @@ |
// JavaScript example: 'array[index](1, 2, 3)' |
// ------------------------------------------- |
- // Load the function to call from the property through a reference. |
- Reference ref(this, property); |
- ref.GetValueAndSpill(); // receiver |
- |
- // Pass receiver to called function. |
+ LoadAndSpill(property->obj()); |
+ LoadAndSpill(property->key()); |
+ EmitKeyedLoad(false); |
+ frame_->Drop(); // key |
+ // Put the function below the receiver. |
if (property->is_synthetic()) { |
+ // Use the global receiver. |
+ frame_->Drop(); |
+ frame_->EmitPush(r0); |
LoadGlobalReceiver(r0); |
} else { |
- __ ldr(r0, frame_->ElementAt(ref.size())); |
- frame_->EmitPush(r0); |
+ frame_->EmitPop(r1); // receiver |
+ frame_->EmitPush(r0); // function |
+ frame_->EmitPush(r1); // receiver |
} |
// Call the function. |
@@ -3807,7 +3805,9 @@ |
frame_->EmitPush(r0); |
} |
- { Reference target(this, node->expression()); |
+ // A constant reference is not saved to, so a constant reference is not a |
+ // compound assignment reference. |
+ { Reference target(this, node->expression(), !is_const); |
if (target.is_illegal()) { |
// Spoof the virtual frame to have the expected height (one higher |
// than on entry). |
@@ -4268,6 +4268,16 @@ |
} |
+void CodeGenerator::EmitKeyedLoad(bool is_global) { |
+ Comment cmnt(masm_, "[ Load from keyed Property"); |
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
+ RelocInfo::Mode rmode = is_global |
+ ? RelocInfo::CODE_TARGET_CONTEXT |
+ : RelocInfo::CODE_TARGET; |
+ frame_->CallCodeObject(ic, rmode, 0); |
+} |
+ |
+ |
#ifdef DEBUG |
bool CodeGenerator::HasValidEntryRegisters() { return true; } |
#endif |
@@ -4334,23 +4344,21 @@ |
case KEYED: { |
// TODO(181): Implement inlined version of array indexing once |
// loop nesting is properly tracked on ARM. |
- VirtualFrame* frame = cgen_->frame(); |
- Comment cmnt(masm, "[ Load from keyed Property"); |
ASSERT(property != NULL); |
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
Variable* var = expression_->AsVariableProxy()->AsVariable(); |
ASSERT(var == NULL || var->is_global()); |
- RelocInfo::Mode rmode = (var == NULL) |
- ? RelocInfo::CODE_TARGET |
- : RelocInfo::CODE_TARGET_CONTEXT; |
- frame->CallCodeObject(ic, rmode, 0); |
- frame->EmitPush(r0); |
+ cgen_->EmitKeyedLoad(var != NULL); |
+ cgen_->frame()->EmitPush(r0); |
break; |
} |
default: |
UNREACHABLE(); |
} |
+ |
+ if (!persist_after_get_) { |
+ cgen_->UnloadReference(this); |
+ } |
} |
@@ -4412,6 +4420,7 @@ |
default: |
UNREACHABLE(); |
} |
+ cgen_->UnloadReference(this); |
} |