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

Unified Diff: src/codegen-arm.cc

Issue 9182: Emit pushes and pops through the virtual frame on ARM. Merging of... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 1 month 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 | « src/codegen-arm.h ('k') | src/codegen-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codegen-arm.cc
===================================================================
--- src/codegen-arm.cc (revision 703)
+++ src/codegen-arm.cc (working copy)
@@ -49,6 +49,72 @@
}
+void VirtualFrame::Enter() {
+ Comment cmnt(masm_, "[ Enter JS frame");
+#ifdef DEBUG
+ { Label done, fail;
+ __ tst(r1, Operand(kSmiTagMask));
+ __ b(eq, &fail);
+ __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+ __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+ __ b(eq, &done);
+ __ bind(&fail);
+ __ stop("CodeGenerator::EnterJSFrame - r1 not a function");
+ __ bind(&done);
+ }
+#endif // DEBUG
+
+ __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
+ // Adjust FP to point to saved FP.
+ __ add(fp, sp, Operand(2 * kPointerSize));
+}
+
+
+void VirtualFrame::Exit() {
+ Comment cmnt(masm_, "[ Exit JS frame");
+ // Drop the execution stack down to the frame pointer and restore the caller
+ // frame pointer and return address.
+ __ mov(sp, fp);
+ __ ldm(ia_w, sp, fp.bit() | lr.bit());
+}
+
+
+void VirtualFrame::AllocateLocals() {
+ if (frame_local_count_ > 0) {
+ Comment cmnt(masm_, "[ Allocate space for locals");
+ // Initialize stack slots with 'undefined' value.
+ __ mov(ip, Operand(Factory::undefined_value()));
+ for (int i = 0; i < frame_local_count_; i++) {
+ __ push(ip);
+ }
+ }
+}
+
+
+void VirtualFrame::Drop(int count) {
+ ASSERT(count >= 0);
+ if (count > 0) {
+ __ add(sp, sp, Operand(count * kPointerSize));
+ }
+}
+
+
+void VirtualFrame::Pop() {
+ __ add(sp, sp, Operand(kPointerSize));
iposva 2008/11/06 18:18:34 Shouldn't this just call Drop(1)?
Kevin Millikin (Chromium) 2008/11/07 08:19:10 Fixed.
+}
+
+
+void VirtualFrame::Pop(Register reg) {
+ __ pop(reg);
+}
+
+
+void VirtualFrame::Push(Register reg) {
+ __ push(reg);
+}
+
+
// -------------------------------------------------------------------------
// CodeGenState implementation.
@@ -99,7 +165,6 @@
// Calling conventions:
-
// r0: the number of arguments
// fp: frame pointer
// sp: stack pointer
@@ -127,9 +192,7 @@
// pp: caller's parameter pointer
// cp: callee's context
iposva 2008/11/06 18:18:34 ditto
- { Comment cmnt(masm_, "[ enter JS frame");
- EnterJSFrame();
- }
+ frame_->Enter();
// tos: code slot
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
@@ -139,20 +202,13 @@
#endif
// Allocate space for locals and initialize them.
- if (scope_->num_stack_slots() > 0) {
- Comment cmnt(masm_, "[ allocate space for locals");
- // Initialize stack slots with 'undefined' value.
- __ mov(ip, Operand(Factory::undefined_value()));
- for (int i = 0; i < scope_->num_stack_slots(); i++) {
- __ push(ip);
- }
- }
+ frame_->AllocateLocals();
if (scope_->num_heap_slots() > 0) {
// Allocate local context.
// Get outer context and create a new context based on it.
__ ldr(r0, frame_->Function());
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result
if (kDebug) {
@@ -166,7 +222,7 @@
__ str(cp, frame_->Context());
}
- // TODO(1241774): Improve this code!!!
+ // TODO(1241774): Improve this code:
// 1) only needed if we have a context
// 2) no need to recompute context ptr every single time
// 3) don't copy parameter operand code from SlotOperand!
@@ -198,9 +254,9 @@
}
}
- // Store the arguments object.
- // This must happen after context initialization because
- // the arguments array may be stored in the context!
+ // Store the arguments object. This must happen after context
+ // initialization because the arguments object may be stored in the
+ // context.
if (scope_->arguments() != NULL) {
ASSERT(scope_->arguments_shadow() != NULL);
Comment cmnt(masm_, "[ allocate arguments object");
@@ -215,35 +271,31 @@
__ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
__ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
__ CallStub(&stub);
- __ push(r0);
+ frame_->Push(r0);
arguments_ref.SetValue(NOT_CONST_INIT);
}
shadow_ref.SetValue(NOT_CONST_INIT);
}
- __ pop(r0); // Value is no longer needed.
+ frame_->Pop(); // Value is no longer needed.
}
- // Generate code to 'execute' declarations and initialize
- // functions (source elements). In case of an illegal
- // redeclaration we need to handle that instead of processing the
- // declarations.
+ // Generate code to 'execute' declarations and initialize functions
+ // (source elements). In case of an illegal redeclaration we need to
+ // handle that instead of processing the declarations.
if (scope_->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ illegal redeclarations");
scope_->VisitIllegalRedeclaration(this);
} else {
Comment cmnt(masm_, "[ declarations");
- // ProcessDeclarations calls DeclareGlobals indirectly
ProcessDeclarations(scope_->declarations());
-
- // Bail out if a stack-overflow exception occurred when
- // processing declarations.
+ // Bail out if a stack-overflow exception occurred when processing
+ // declarations.
if (HasStackOverflow()) return;
}
if (FLAG_trace) {
- // Push a valid value as the parameter. The runtime call only uses
- // it as the return value to indicate non-failure.
__ CallRuntime(Runtime::kTraceEnter, 0);
+ // Ignore the return value.
}
CheckStack();
@@ -258,6 +310,7 @@
is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
if (should_trace) {
__ CallRuntime(Runtime::kDebugTrace, 0);
+ // Ignore the return value.
}
#endif
VisitStatements(body);
@@ -276,13 +329,13 @@
if (FLAG_trace) {
// Push the return value on the stack as the parameter.
// Runtime::TraceExit returns the parameter as it is.
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kTraceExit, 1);
}
// Tear down the frame which will restore the caller's frame pointer and the
// link register.
- ExitJSFrame();
+ frame_->Exit();
__ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
__ mov(pc, lr);
@@ -346,16 +399,17 @@
}
-// Loads a value on the stack. If it is a boolean value, the result may have
-// been (partially) translated into branches, or it may have set the condition
-// code register. If force_cc is set, the value is forced to set the condition
-// code register and no value is pushed. If the condition code register was set,
-// has_cc() is true and cc_reg_ contains the condition to test for 'true'.
+// Loads a value on TOS. If it is a boolean value, the result may have been
+// (partially) translated into branches, or it may have set the condition
+// code register. If force_cc is set, the value is forced to set the
+// condition code register and no value is pushed. If the condition code
+// register was set, has_cc() is true and cc_reg_ contains the condition to
+// test for 'true'.
void CodeGenerator::LoadCondition(Expression* x,
- TypeofState typeof_state,
- Label* true_target,
- Label* false_target,
- bool force_cc) {
+ TypeofState typeof_state,
+ Label* true_target,
+ Label* false_target,
+ bool force_cc) {
ASSERT(!has_cc());
{ CodeGenState new_state(this, typeof_state, true_target, false_target);
@@ -363,6 +417,13 @@
}
if (force_cc && !has_cc()) {
// Convert the TOS value to a boolean in the condition code register.
+ // Visiting an expression may possibly choose neither (a) to leave a
+ // value in the condition code register nor (b) to leave a value in TOS
+ // (eg, by compiling to only jumps to the targets). In that case the
+ // code generated by ToBoolean is wrong because it assumes the value of
+ // the expression in TOS. So long as there is always a value in TOS or
+ // the condition code register when control falls through to here (there
+ // is), the code generated by ToBoolean is dead and therefore safe.
ToBoolean(true_target, false_target);
}
ASSERT(has_cc() || !force_cc);
@@ -379,11 +440,11 @@
Label loaded, materialize_true;
__ b(cc_reg_, &materialize_true);
__ mov(r0, Operand(Factory::false_value()));
- __ push(r0);
+ frame_->Push(r0);
__ b(&loaded);
__ bind(&materialize_true);
__ mov(r0, Operand(Factory::true_value()));
- __ push(r0);
+ frame_->Push(r0);
__ bind(&loaded);
cc_reg_ = al;
}
@@ -399,7 +460,7 @@
if (true_target.is_linked()) {
__ bind(&true_target);
__ mov(r0, Operand(Factory::true_value()));
- __ push(r0);
+ frame_->Push(r0);
}
// if both "true" and "false" need to be reincarnated,
// jump across code for "false"
@@ -409,7 +470,7 @@
if (false_target.is_linked()) {
__ bind(&false_target);
__ mov(r0, Operand(Factory::false_value()));
- __ push(r0);
+ frame_->Push(r0);
}
// everything is loaded at this point
__ bind(&loaded);
@@ -420,14 +481,15 @@
void CodeGenerator::LoadGlobal() {
__ ldr(r0, GlobalObject());
- __ push(r0);
+ frame_->Push(r0);
}
-void CodeGenerator::LoadGlobalReceiver(Register s) {
- __ ldr(s, ContextOperand(cp, Context::GLOBAL_INDEX));
- __ ldr(s, FieldMemOperand(s, GlobalObject::kGlobalReceiverOffset));
- __ push(s);
+void CodeGenerator::LoadGlobalReceiver(Register scratch) {
+ __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX));
+ __ ldr(scratch,
+ FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset));
+ frame_->Push(scratch);
}
@@ -465,7 +527,6 @@
void CodeGenerator::LoadReference(Reference* ref) {
Comment cmnt(masm_, "[ LoadReference");
-
Expression* e = ref->expression();
Property* property = e->AsProperty();
Variable* var = e->AsVariableProxy()->AsVariable();
@@ -507,15 +568,15 @@
void CodeGenerator::UnloadReference(Reference* ref) {
+ // Pop a reference from the stack while preserving TOS.
Comment cmnt(masm_, "[ UnloadReference");
-
int size = ref->size();
if (size <= 0) {
iposva 2008/11/06 18:18:34 Can a reference size ever be negative? If not, the
Kevin Millikin (Chromium) 2008/11/07 08:19:10 Yes it can be negative, but we should probably cha
// Do nothing. No popping is necessary.
} else {
- __ pop(r0);
- __ add(sp, sp, Operand(size * kPointerSize));
- __ push(r0);
+ frame_->Pop(r0);
+ frame_->Drop(size);
+ frame_->Push(r0);
}
}
@@ -524,10 +585,10 @@
// register to a boolean in the condition code register. The code
// may jump to 'false_target' in case the register converts to 'false'.
void CodeGenerator::ToBoolean(Label* true_target,
- Label* false_target) {
+ Label* false_target) {
// Note: The generated code snippet does not change stack variables.
// Only the condition code should be set.
- __ pop(r0);
+ frame_->Pop(r0);
// Fast case checks
@@ -550,10 +611,9 @@
__ b(eq, true_target);
// Slow case: call the runtime.
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kToBool, 1);
-
- // Convert result (r0) to condition code
+ // Convert the result (r0) to a condition code.
__ cmp(r0, Operand(Factory::false_value()));
cc_reg_ = ne;
@@ -654,8 +714,8 @@
case Token::SHL:
case Token::SHR:
case Token::SAR: {
- __ pop(r0); // r0 : y
- __ pop(r1); // r1 : x
+ frame_->Pop(r0); // r0 : y
+ frame_->Pop(r1); // r1 : x
GenericBinaryOpStub stub(op);
__ CallStub(&stub);
break;
@@ -674,9 +734,9 @@
}
case Token::COMMA:
- __ pop(r0);
+ frame_->Pop(r0);
// simply discard left value
- __ pop();
+ frame_->Pop();
break;
default:
@@ -764,8 +824,8 @@
void CodeGenerator::SmiOperation(Token::Value op,
- Handle<Object> value,
- bool reversed) {
+ Handle<Object> value,
+ bool reversed) {
// NOTE: This is an attempt to inline (a bit) more of the code for
// some possible smi operations (like + and -) when (at least) one
// of the operands is a literal smi. With this optimization, the
@@ -778,7 +838,7 @@
int int_value = Smi::cast(*value)->value();
Label exit;
- __ pop(r0);
+ frame_->Pop(r0);
switch (op) {
case Token::ADD: {
@@ -831,8 +891,8 @@
case Token::SAR: {
if (reversed) {
__ mov(ip, Operand(value));
- __ push(ip);
- __ push(r0);
+ frame_->Push(ip);
+ frame_->Push(r0);
GenericBinaryOperation(op);
} else {
@@ -882,13 +942,13 @@
default:
if (!reversed) {
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(value));
- __ push(r0);
+ frame_->Push(r0);
} else {
__ mov(ip, Operand(value));
- __ push(ip);
- __ push(r0);
+ frame_->Push(ip);
+ frame_->Push(r0);
}
GenericBinaryOperation(op);
break;
@@ -910,18 +970,18 @@
// Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
if (cc == gt || cc == le) {
cc = ReverseCondition(cc);
- __ pop(r1);
- __ pop(r0);
+ frame_->Pop(r1);
+ frame_->Pop(r0);
} else {
- __ pop(r0);
- __ pop(r1);
+ frame_->Pop(r0);
+ frame_->Pop(r1);
}
__ orr(r2, r0, Operand(r1));
__ tst(r2, Operand(kSmiTagMask));
__ b(eq, &smi);
// Perform non-smi comparison by runtime call.
- __ push(r1);
+ frame_->Push(r1);
// Figure out which native to call and setup the arguments.
Builtins::JavaScript native;
@@ -938,14 +998,14 @@
ASSERT(cc == gt || cc == ge); // remaining cases
ncr = LESS;
}
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(Smi::FromInt(ncr)));
argc = 2;
}
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(argc));
__ InvokeBuiltin(native, CALL_JS);
__ cmp(r0, Operand(0));
@@ -995,7 +1055,7 @@
// Restore context and pop function from the stack.
__ ldr(cp, frame_->Context());
- __ pop(); // discard the TOS
+ frame_->Pop(); // discard the TOS
}
@@ -1027,10 +1087,10 @@
void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
__ mov(r0, Operand(pairs));
- __ push(r0);
- __ push(cp);
+ frame_->Push(r0);
+ frame_->Push(cp);
__ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// The result is discarded.
}
@@ -1050,26 +1110,26 @@
// during variable resolution and must have mode DYNAMIC.
ASSERT(var->mode() == Variable::DYNAMIC);
// For now, just do a runtime call.
- __ push(cp);
+ frame_->Push(cp);
__ mov(r0, Operand(var->name()));
- __ push(r0);
+ frame_->Push(r0);
// Declaration nodes are always declared in only two modes.
ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
__ mov(r0, Operand(Smi::FromInt(attr)));
- __ push(r0);
+ frame_->Push(r0);
// Push initial value, if any.
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
if (node->mode() == Variable::CONST) {
__ mov(r0, Operand(Factory::the_hole_value()));
- __ push(r0);
+ frame_->Push(r0);
} else if (node->fun() != NULL) {
Load(node->fun());
} else {
__ mov(r0, Operand(0)); // no initial value!
- __ push(r0);
+ frame_->Push(r0);
}
__ CallRuntime(Runtime::kDeclareContextSlot, 4);
// Ignore the return value (declarations are statements).
@@ -1096,7 +1156,7 @@
// safe to pop the value lying on top of the reference before unloading
// the reference itself (which preserves the top of stack) because we
// know it is a zero-sized reference.
- __ pop();
+ frame_->Pop();
}
}
@@ -1107,7 +1167,7 @@
Expression* expression = node->expression();
expression->MarkAsStatement();
Load(expression);
- __ pop();
+ frame_->Pop();
}
@@ -1172,7 +1232,7 @@
if (has_cc()) {
cc_reg_ = al;
} else {
- __ pop(r0); // __ Pop(no_reg)
+ frame_->Pop();
}
}
@@ -1182,10 +1242,8 @@
void CodeGenerator::CleanStack(int num_bytes) {
- ASSERT(num_bytes >= 0);
- if (num_bytes > 0) {
- __ add(sp, sp, Operand(num_bytes));
- }
+ ASSERT(num_bytes % kPointerSize == 0);
+ frame_->Drop(num_bytes / kPointerSize);
}
@@ -1210,7 +1268,7 @@
if (FLAG_debug_info) RecordStatementPosition(node);
Load(node->expression());
// Move the function result into r0.
- __ pop(r0);
+ frame_->Pop(r0);
__ b(&function_return_);
}
@@ -1261,7 +1319,7 @@
ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
- __ pop(r0);
+ frame_->Pop(r0);
// Test for a Smi value in a HeapNumber.
Label is_smi;
@@ -1271,7 +1329,7 @@
__ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
__ cmp(r1, Operand(HEAP_NUMBER_TYPE));
__ b(ne, fail_label);
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kNumberToSmi, 1);
__ bind(&is_smi);
@@ -1340,7 +1398,7 @@
__ bind(&next);
next.Unuse();
__ ldr(r0, frame_->Top());
- __ push(r0); // duplicate TOS
+ frame_->Push(r0); // duplicate TOS
Load(clause->label());
Comparison(eq, true);
Branch(false, &next);
@@ -1348,7 +1406,7 @@
// Entering the case statement for the first time. Remove the switch value
// from the stack.
- __ pop(r0);
+ frame_->Pop();
// Generate code for the body.
// This is also the target for the fall through from the previous case's
@@ -1367,7 +1425,7 @@
__ b(&default_case);
} else {
// Remove the switch value from the stack.
- __ pop(r0);
+ frame_->Pop();
}
__ bind(&fall_through);
@@ -1463,7 +1521,7 @@
// Get the object to enumerate over (converted to JSObject).
Load(node->enumerable());
- __ pop(r0);
+ frame_->Pop(r0);
// Both SpiderMonkey and kjs ignore null and undefined in contrast
// to the specification. 12.6.4 mandates a call to ToObject.
@@ -1488,7 +1546,7 @@
__ b(hs, &jsobject);
__ bind(&primitive);
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(0));
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
@@ -1496,8 +1554,8 @@
__ bind(&jsobject);
// Get the set of properties (as a FixedArray or Map).
- __ push(r0); // duplicate the object being enumerated
- __ push(r0);
+ frame_->Push(r0); // duplicate the object being enumerated
+ frame_->Push(r0);
__ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
// If we got a Map, we can do a fast modification check.
@@ -1514,28 +1572,28 @@
__ ldr(r2,
FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
- __ push(r0); // map
- __ push(r2); // enum cache bridge cache
+ frame_->Push(r0); // map
+ frame_->Push(r2); // enum cache bridge cache
__ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset));
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(Smi::FromInt(0)));
- __ push(r0);
+ frame_->Push(r0);
__ b(&entry);
__ bind(&fixed_array);
__ mov(r1, Operand(Smi::FromInt(0)));
- __ push(r1); // insert 0 in place of Map
- __ push(r0);
+ frame_->Push(r1); // insert 0 in place of Map
+ frame_->Push(r0);
// Push the length of the array and the initial index onto the stack.
__ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset));
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(Smi::FromInt(0))); // init index
- __ push(r0);
+ frame_->Push(r0);
__ b(&entry);
@@ -1546,9 +1604,9 @@
// Next.
__ bind(node->continue_target());
__ bind(&next);
- __ pop(r0);
+ frame_->Pop(r0);
__ add(r0, r0, Operand(Smi::FromInt(1)));
- __ push(r0);
+ frame_->Push(r0);
// Condition.
__ bind(&entry);
@@ -1581,8 +1639,8 @@
// Convert the entry to a string (or null if it isn't a property anymore).
__ ldr(r0, frame_->Element(4)); // push enumerable
- __ push(r0);
- __ push(r3); // push entry
+ frame_->Push(r0);
+ frame_->Push(r3); // push entry
__ mov(r0, Operand(1));
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS);
__ mov(r3, Operand(r0));
@@ -1596,12 +1654,12 @@
// Store the entry in the 'each' expression and take another spin in the loop.
// r3: i'th entry of the enum cache (or string there of)
- __ push(r3); // push entry
+ frame_->Push(r3); // push entry
{ Reference each(this, node->each());
if (!each.is_illegal()) {
if (each.size() > 0) {
__ ldr(r0, frame_->Element(each.size()));
- __ push(r0);
+ frame_->Push(r0);
}
// 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
@@ -1613,20 +1671,20 @@
// ie, now the topmost value of the non-zero sized reference), since
// we will discard the top of stack after unloading the reference
// anyway.
- __ pop(r0);
+ frame_->Pop(r0);
}
}
}
// Discard the i'th entry pushed above or else the remainder of the
// reference, whichever is currently on top of the stack.
- __ pop();
+ frame_->Pop();
CheckStack(); // TODO(1222600): ignore if body contains calls.
__ jmp(&loop);
// Cleanup.
__ bind(&cleanup);
__ bind(node->break_target());
- __ add(sp, sp, Operand(5 * kPointerSize));
+ frame_->Drop(5);
// Exit.
__ bind(&exit);
@@ -1641,11 +1699,10 @@
Label try_block, exit;
__ bl(&try_block);
-
// --- Catch block ---
+ frame_->Push(r0);
// Store the caught exception in the catch variable.
- __ push(r0);
{ Reference ref(this, node->catch_var());
ASSERT(ref.is_slot());
// Here we make use of the convenient property that it doesn't matter
@@ -1655,7 +1712,7 @@
}
// Remove the exception from the stack.
- __ pop();
+ frame_->Pop();
VisitStatements(node->catch_block()->statements());
__ b(&exit);
@@ -1682,7 +1739,7 @@
// Generate code for the statements in the try block.
VisitStatements(node->try_block()->statements());
- __ pop(r0); // Discard the result.
+ frame_->Pop(); // Discard the result.
// Stop the introduced shadowing and count the number of required unlinks.
// After shadowing stops, the original labels are unshadowed and the
@@ -1702,7 +1759,7 @@
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ str(r1, MemOperand(r3));
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
- __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+ frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Code slot popped.
if (nof_unlinks > 0) __ b(&exit);
@@ -1721,7 +1778,7 @@
__ ldr(r1, frame_->Element(kNextIndex));
__ str(r1, MemOperand(r3));
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
- __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+ frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Code slot popped.
__ b(shadows[i]->original_label());
@@ -1744,7 +1801,7 @@
__ bl(&try_block);
- __ push(r0); // save exception object on the stack
+ frame_->Push(r0); // save exception object on the stack
// In case of thrown exceptions, this is where we continue.
__ mov(r2, Operand(Smi::FromInt(THROWING)));
__ b(&finally_block);
@@ -1782,7 +1839,7 @@
// Set the state on the stack to FALLING.
__ mov(r0, Operand(Factory::undefined_value())); // fake TOS
- __ push(r0);
+ frame_->Push(r0);
__ mov(r2, Operand(Smi::FromInt(FALLING)));
if (nof_unlinks > 0) __ b(&unlink);
@@ -1794,11 +1851,11 @@
if (shadows[i]->original_label() == &function_return_) {
// If this label shadowed the function return, materialize the
// return value on the stack.
- __ push(r0);
+ frame_->Push(r0);
} else {
// Fake TOS for labels that shadowed breaks and continues.
__ mov(r0, Operand(Factory::undefined_value()));
- __ push(r0);
+ frame_->Push(r0);
}
__ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
__ b(&unlink);
@@ -1808,7 +1865,7 @@
// Unlink from try chain;
__ bind(&unlink);
- __ pop(r0); // Store TOS in r0 across stack manipulation
+ frame_->Pop(r0); // Store TOS in r0 across stack manipulation
// Reload sp from the top handler, because some statements that we
// break from (eg, for...in) may have left stuff on the stack.
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
@@ -1819,15 +1876,15 @@
__ ldr(r1, frame_->Element(kNextIndex));
__ str(r1, MemOperand(r3));
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
- __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+ frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Code slot popped.
- __ push(r0);
+ frame_->Push(r0);
// --- Finally block ---
__ bind(&finally_block);
// Push the state on the stack.
- __ push(r2);
+ frame_->Push(r2);
// We keep two elements on the stack - the (possibly faked) result
// and the state - while evaluating the finally block. Record it, so
@@ -1840,8 +1897,8 @@
VisitStatements(node->finally_block()->statements());
// Restore state and return value or faked TOS.
- __ pop(r2);
- __ pop(r0);
+ frame_->Pop(r2);
+ frame_->Pop(r0);
break_stack_height_ -= kFinallyStackSize;
// Generate code to jump to the right destination for all used (formerly)
@@ -1865,7 +1922,7 @@
__ b(ne, &exit);
// Rethrow exception.
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kReThrow, 1);
// Done.
@@ -1886,12 +1943,12 @@
// Push the boilerplate on the stack.
__ mov(r0, Operand(boilerplate));
- __ push(r0);
+ frame_->Push(r0);
// Create a new closure.
- __ push(cp);
+ frame_->Push(cp);
__ CallRuntime(Runtime::kNewClosure, 2);
- __ push(r0);
+ frame_->Push(r0);
}
@@ -1932,16 +1989,16 @@
ASSERT(slot->var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call.
- __ push(cp);
+ frame_->Push(cp);
__ mov(r0, Operand(slot->var()->name()));
- __ push(r0);
+ frame_->Push(r0);
if (typeof_state == INSIDE_TYPEOF) {
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
} else {
__ CallRuntime(Runtime::kLoadContextSlot, 2);
}
- __ push(r0);
+ frame_->Push(r0);
} else {
// Note: We would like to keep the assert below, but it fires because of
@@ -1950,16 +2007,16 @@
// Special handling for locals allocated in registers.
__ ldr(r0, SlotOperand(slot, r2));
- __ push(r0);
+ frame_->Push(r0);
if (slot->var()->mode() == Variable::CONST) {
// Const slots may contain 'the hole' value (the constant hasn't been
// initialized yet) which needs to be converted into the 'undefined'
// value.
Comment cmnt(masm_, "[ Unhole const");
- __ pop(r0);
+ frame_->Pop(r0);
__ cmp(r0, Operand(Factory::the_hole_value()));
__ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
- __ push(r0);
+ frame_->Push(r0);
}
}
}
@@ -1989,7 +2046,7 @@
void CodeGenerator::VisitLiteral(Literal* node) {
Comment cmnt(masm_, "[ Literal");
__ mov(r0, Operand(node->handle()));
- __ push(r0);
+ frame_->Push(r0);
}
@@ -2015,19 +2072,19 @@
// If the entry is undefined we call the runtime system to computed
// the literal.
- __ push(r1); // literal array (0)
+ frame_->Push(r1); // literal array (0)
__ mov(r0, Operand(Smi::FromInt(node->literal_index())));
- __ push(r0); // literal index (1)
+ frame_->Push(r0); // literal index (1)
__ mov(r0, Operand(node->pattern())); // RegExp pattern (2)
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(node->flags())); // RegExp flags (3)
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
__ mov(r2, Operand(r0));
__ bind(&done);
// Push the literal.
- __ push(r2);
+ frame_->Push(r2);
}
@@ -2089,11 +2146,11 @@
__ bind(deferred->exit());
// Push the object literal boilerplate.
- __ push(r2);
+ frame_->Push(r2);
// Clone the boilerplate object.
__ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
- __ push(r0); // save the result
+ frame_->Push(r0); // save the result
// r0: cloned object literal
for (int i = 0; i < node->properties()->length(); i++) {
@@ -2104,7 +2161,7 @@
case ObjectLiteral::Property::CONSTANT: break;
case ObjectLiteral::Property::COMPUTED: // fall through
case ObjectLiteral::Property::PROTOTYPE: {
- __ push(r0); // dup the result
+ frame_->Push(r0); // dup the result
Load(key);
Load(value);
__ CallRuntime(Runtime::kSetProperty, 3);
@@ -2113,20 +2170,20 @@
break;
}
case ObjectLiteral::Property::SETTER: {
- __ push(r0);
+ frame_->Push(r0);
Load(key);
__ mov(r0, Operand(Smi::FromInt(1)));
- __ push(r0);
+ frame_->Push(r0);
Load(value);
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ ldr(r0, frame_->Top());
break;
}
case ObjectLiteral::Property::GETTER: {
- __ push(r0);
+ frame_->Push(r0);
Load(key);
__ mov(r0, Operand(Smi::FromInt(0)));
- __ push(r0);
+ frame_->Push(r0);
Load(value);
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ ldr(r0, frame_->Top());
@@ -2142,15 +2199,15 @@
// Call runtime to create the array literal.
__ mov(r0, Operand(node->literals()));
- __ push(r0);
+ frame_->Push(r0);
// Load the function of this frame.
__ ldr(r0, frame_->Function());
__ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kCreateArrayLiteral, 2);
// Push the resulting array literal on the stack.
- __ push(r0);
+ frame_->Push(r0);
// Generate code to set the elements in the array that are not
// literals.
@@ -2162,7 +2219,7 @@
if (value->AsLiteral() == NULL) {
// The property must be set by generated code.
Load(value);
- __ pop(r0);
+ frame_->Pop(r0);
// Fetch the object literal
__ ldr(r1, frame_->Top());
@@ -2198,12 +2255,12 @@
Literal* literal = node->value()->AsLiteral();
if (literal != NULL && literal->handle()->IsSmi()) {
SmiOperation(node->binary_op(), literal->handle(), false);
- __ push(r0);
+ frame_->Push(r0);
} else {
Load(node->value());
GenericBinaryOperation(node->binary_op());
- __ push(r0);
+ frame_->Push(r0);
}
}
@@ -2233,7 +2290,7 @@
Load(node->exception());
__ RecordPosition(node->position());
__ CallRuntime(Runtime::kThrow, 1);
- __ push(r0);
+ frame_->Push(r0);
}
@@ -2274,7 +2331,7 @@
// Push the name of the function and the receiver onto the stack.
__ mov(r0, Operand(var->name()));
- __ push(r0);
+ frame_->Push(r0);
// Pass the global object as the receiver and let the IC stub
// patch the stack to use the global proxy as 'this' in the
@@ -2290,8 +2347,8 @@
__ Call(stub, RelocInfo::CODE_TARGET_CONTEXT);
__ ldr(cp, frame_->Context());
// Remove the function from the stack.
- __ pop();
- __ push(r0);
+ frame_->Pop();
+ frame_->Push(r0);
} else if (var != NULL && var->slot() != NULL &&
var->slot()->type() == Slot::LOOKUP) {
@@ -2300,19 +2357,19 @@
// ----------------------------------
// Load the function
- __ push(cp);
+ frame_->Push(cp);
__ mov(r0, Operand(var->name()));
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kLoadContextSlot, 2);
// r0: slot value; r1: receiver
// Load the receiver.
- __ push(r0); // function
- __ push(r1); // receiver
+ frame_->Push(r0); // function
+ frame_->Push(r1); // receiver
// Call the function.
CallWithArguments(args, node->position());
- __ push(r0);
+ frame_->Push(r0);
} else if (property != NULL) {
// Check if the key is a literal string.
@@ -2325,7 +2382,7 @@
// Push the name of the function and the receiver onto the stack.
__ mov(r0, Operand(literal->handle()));
- __ push(r0);
+ frame_->Push(r0);
Load(property->obj());
// Load the arguments.
@@ -2338,9 +2395,9 @@
__ ldr(cp, frame_->Context());
// Remove the function from the stack.
- __ pop();
+ frame_->Pop();
- __ push(r0); // push after get rid of function from the stack
+ frame_->Push(r0); // push after get rid of function from the stack
} else {
// -------------------------------------------
@@ -2353,10 +2410,10 @@
// Pass receiver to called function.
__ ldr(r0, frame_->Element(ref.size()));
- __ push(r0);
+ frame_->Push(r0);
// Call the function.
CallWithArguments(args, node->position());
- __ push(r0);
+ frame_->Push(r0);
}
} else {
@@ -2372,7 +2429,7 @@
// Call the function.
CallWithArguments(args, node->position());
- __ push(r0);
+ frame_->Push(r0);
}
}
@@ -2417,7 +2474,7 @@
ASSERT(args->length() == 1);
Label leave;
Load(args->at(0));
- __ pop(r0); // r0 contains object.
+ frame_->Pop(r0); // r0 contains object.
// if (object->IsSmi()) return the object.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &leave);
@@ -2430,7 +2487,7 @@
// Load the value.
__ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
__ bind(&leave);
- __ push(r0);
+ frame_->Push(r0);
}
@@ -2439,8 +2496,8 @@
Label leave;
Load(args->at(0)); // Load the object.
Load(args->at(1)); // Load the value.
- __ pop(r0); // r0 contains value
- __ pop(r1); // r1 contains object
+ frame_->Pop(r0); // r0 contains value
+ frame_->Pop(r1); // r1 contains object
// if (object->IsSmi()) return object.
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &leave);
@@ -2457,14 +2514,14 @@
__ RecordWrite(r1, r2, r3);
// Leave.
__ bind(&leave);
- __ push(r0);
+ frame_->Push(r0);
}
void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
Load(args->at(0));
- __ pop(r0);
+ frame_->Pop(r0);
__ tst(r0, Operand(kSmiTagMask));
cc_reg_ = eq;
}
@@ -2473,7 +2530,7 @@
void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
Load(args->at(0));
- __ pop(r0);
+ frame_->Pop(r0);
__ tst(r0, Operand(kSmiTagMask | 0x80000000));
cc_reg_ = eq;
}
@@ -2485,7 +2542,7 @@
void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
__ mov(r0, Operand(Factory::undefined_value()));
- __ push(r0);
+ frame_->Push(r0);
}
@@ -2496,7 +2553,7 @@
// We need the CC bits to come out as not_equal in the case where the
// object is a smi. This can't be done with the usual test opcode so
// we use XOR to get the right CC bits.
- __ pop(r0);
+ frame_->Pop(r0);
__ and_(r1, r0, Operand(kSmiTagMask));
__ eor(r1, r1, Operand(kSmiTagMask), SetCC);
__ b(ne, &answer);
@@ -2520,7 +2577,7 @@
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
__ CallStub(&stub);
- __ push(r0);
+ frame_->Push(r0);
}
@@ -2530,13 +2587,13 @@
// Satisfy contract with ArgumentsAccessStub:
// Load the key into r1 and the formal parameters count into r0.
Load(args->at(0));
- __ pop(r1);
+ frame_->Pop(r1);
__ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
// Call the shared stub to get to arguments[key].
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
__ CallStub(&stub);
- __ push(r0);
+ frame_->Push(r0);
}
@@ -2546,8 +2603,8 @@
// Load the two objects into registers and perform the comparison.
Load(args->at(0));
Load(args->at(1));
- __ pop(r0);
- __ pop(r1);
+ frame_->Pop(r0);
+ frame_->Pop(r1);
__ cmp(r0, Operand(r1));
cc_reg_ = eq;
}
@@ -2566,16 +2623,16 @@
// Call the C runtime function.
__ CallRuntime(function, args->length());
- __ push(r0);
+ frame_->Push(r0);
} else {
// Prepare stack for calling JS runtime function.
__ mov(r0, Operand(node->name()));
- __ push(r0);
+ frame_->Push(r0);
// Push the builtins object found in the current global object.
__ ldr(r1, GlobalObject());
__ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
- __ push(r0);
+ frame_->Push(r0);
for (int i = 0; i < args->length(); i++) Load(args->at(i));
@@ -2583,8 +2640,8 @@
Handle<Code> stub = ComputeCallInitialize(args->length());
__ Call(stub, RelocInfo::CODE_TARGET);
__ ldr(cp, frame_->Context());
- __ pop();
- __ push(r0);
+ frame_->Pop();
+ frame_->Push(r0);
}
}
@@ -2616,20 +2673,20 @@
if (variable->is_global()) {
LoadGlobal();
__ mov(r0, Operand(variable->name()));
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin(Builtins::DELETE, CALL_JS);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
// lookup the context holding the named variable
- __ push(cp);
+ frame_->Push(cp);
__ mov(r0, Operand(variable->name()));
- __ push(r0);
+ frame_->Push(r0);
__ CallRuntime(Runtime::kLookupContext, 2);
// r0: context
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(variable->name()));
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin(Builtins::DELETE, CALL_JS);
@@ -2642,21 +2699,21 @@
} else {
// Default: Result of deleting expressions is true.
Load(node->expression()); // may have side-effects
- __ pop();
+ frame_->Pop();
__ mov(r0, Operand(Factory::true_value()));
}
- __ push(r0);
+ frame_->Push(r0);
} else if (op == Token::TYPEOF) {
// Special case for loading the typeof expression; see comment on
// LoadTypeofExpression().
LoadTypeofExpression(node->expression());
__ CallRuntime(Runtime::kTypeof, 1);
- __ push(r0); // r0 has result
+ frame_->Push(r0); // r0 has result
} else {
Load(node->expression());
- __ pop(r0);
+ frame_->Pop(r0);
switch (op) {
case Token::NOT:
case Token::DELETE:
@@ -2677,7 +2734,7 @@
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &smi_label);
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(0)); // not counting receiver
__ InvokeBuiltin(Builtins::BIT_NOT, CALL_JS);
@@ -2700,7 +2757,7 @@
Label continue_label;
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &continue_label);
- __ push(r0);
+ frame_->Push(r0);
__ mov(r0, Operand(0)); // not counting receiver
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
__ bind(&continue_label);
@@ -2709,7 +2766,7 @@
default:
UNREACHABLE();
}
- __ push(r0); // r0 has result
+ frame_->Push(r0); // r0 has result
}
}
@@ -2726,13 +2783,13 @@
// Postfix: Make room for the result.
if (is_postfix) {
__ mov(r0, Operand(0));
- __ push(r0);
+ frame_->Push(r0);
}
{ Reference target(this, node->expression());
if (target.is_illegal()) return;
target.GetValue(NOT_INSIDE_TYPEOF);
- __ pop(r0);
+ frame_->Pop(r0);
Label slow, exit;
@@ -2787,12 +2844,12 @@
// Store the new value in the target if not const.
__ bind(&exit);
- __ push(r0);
+ frame_->Push(r0);
if (!is_const) target.SetValue(NOT_CONST_INIT);
}
// Postfix: Discard the new value and use the old.
- if (is_postfix) __ pop(r0);
+ if (is_postfix) frame_->Pop(r0);
}
@@ -2834,7 +2891,7 @@
Label pop_and_continue, exit;
__ ldr(r0, frame_->Top()); // dup the stack top
- __ push(r0);
+ frame_->Push(r0);
// Avoid popping the result if it converts to 'false' using the
// standard ToBoolean() conversion as described in ECMA-262,
// section 9.2, page 30.
@@ -2843,7 +2900,7 @@
// Pop the result of evaluating the first part.
__ bind(&pop_and_continue);
- __ pop(r0);
+ frame_->Pop(r0);
// Evaluate right side expression.
__ bind(&is_true);
@@ -2875,7 +2932,7 @@
Label pop_and_continue, exit;
__ ldr(r0, frame_->Top());
- __ push(r0);
+ frame_->Push(r0);
// Avoid popping the result if it converts to 'true' using the
// standard ToBoolean() conversion as described in ECMA-262,
// section 9.2, page 30.
@@ -2884,7 +2941,7 @@
// Pop the result of evaluating the first part.
__ bind(&pop_and_continue);
- __ pop(r0);
+ frame_->Pop(r0);
// Evaluate right side expression.
__ bind(&is_false);
@@ -2913,14 +2970,14 @@
Load(node->right());
GenericBinaryOperation(node->op());
}
- __ push(r0);
+ frame_->Push(r0);
}
}
void CodeGenerator::VisitThisFunction(ThisFunction* node) {
__ ldr(r0, frame_->Function());
- __ push(r0);
+ frame_->Push(r0);
}
@@ -2946,7 +3003,7 @@
if (left_is_null || right_is_null) {
Load(left_is_null ? right : left);
Label exit, undetectable;
- __ pop(r0);
+ frame_->Pop(r0);
__ cmp(r0, Operand(Factory::null_value()));
// The 'null' value is only equal to 'undefined' if using
@@ -2990,7 +3047,7 @@
// Load the operand, move it to register r1.
LoadTypeofExpression(operation->expression());
- __ pop(r1);
+ frame_->Pop(r1);
if (check->Equals(Heap::number_symbol())) {
__ tst(r1, Operand(kSmiTagMask));
@@ -3102,7 +3159,7 @@
case Token::IN:
__ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin(Builtins::IN, CALL_JS);
- __ push(r0);
+ frame_->Push(r0);
break;
case Token::INSTANCEOF:
@@ -3127,34 +3184,6 @@
}
-void CodeGenerator::EnterJSFrame() {
-#if defined(DEBUG)
- { Label done, fail;
- __ tst(r1, Operand(kSmiTagMask));
- __ b(eq, &fail);
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
- __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
- __ cmp(r2, Operand(JS_FUNCTION_TYPE));
- __ b(eq, &done);
- __ bind(&fail);
- __ stop("CodeGenerator::EnterJSFrame - r1 not a function");
- __ bind(&done);
- }
-#endif // DEBUG
-
- __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
- __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP.
-}
-
-
-void CodeGenerator::ExitJSFrame() {
- // Drop the execution stack down to the frame pointer and restore the caller
- // frame pointer and return address.
- __ mov(sp, fp);
- __ ldm(ia_w, sp, fp.bit() | lr.bit());
-}
-
-
#undef __
#define __ masm->
@@ -3179,6 +3208,7 @@
ASSERT(!is_illegal());
ASSERT(!cgen_->has_cc());
MacroAssembler* masm = cgen_->masm();
+ VirtualFrame* frame = cgen_->frame();
Property* property = expression_->AsProperty();
if (property != NULL) {
__ RecordPosition(property->position());
@@ -3212,7 +3242,7 @@
} else {
__ Call(ic, RelocInfo::CODE_TARGET);
}
- __ push(r0);
+ frame->Push(r0);
break;
}
@@ -3224,7 +3254,7 @@
// TODO(1224671): Implement inline caching for keyed loads as on ia32.
GetPropertyStub stub;
__ CallStub(&stub);
- __ push(r0);
+ frame->Push(r0);
break;
}
@@ -3238,6 +3268,7 @@
ASSERT(!is_illegal());
ASSERT(!cgen_->has_cc());
MacroAssembler* masm = cgen_->masm();
+ VirtualFrame* frame = cgen_->frame();
Property* property = expression_->AsProperty();
if (property != NULL) {
__ RecordPosition(property->position());
@@ -3252,9 +3283,9 @@
ASSERT(slot->var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call.
- __ push(cp);
+ frame->Push(cp);
__ mov(r0, Operand(slot->var()->name()));
- __ push(r0);
+ frame->Push(r0);
if (init_state == CONST_INIT) {
// Same as the case for a normal store, but ignores attribute
@@ -3278,7 +3309,7 @@
}
// Storing a variable must keep the (new) value on the expression
// stack. This is necessary for compiling assignment expressions.
- __ push(r0);
+ frame->Push(r0);
} else {
ASSERT(slot->var()->mode() != Variable::DYNAMIC);
@@ -3304,9 +3335,9 @@
// initialize consts to 'the hole' value and by doing so, end up
// calling this code. r2 may be loaded with context; used below in
// RecordWrite.
- __ pop(r0);
+ frame->Pop(r0);
__ str(r0, cgen_->SlotOperand(slot, r2));
- __ push(r0);
+ frame->Push(r0);
if (slot->type() == Slot::CONTEXT) {
// Skip write barrier if the written value is a smi.
__ tst(r0, Operand(kSmiTagMask));
@@ -3329,13 +3360,13 @@
case NAMED: {
Comment cmnt(masm, "[ Store to named Property");
// Call the appropriate IC code.
- __ pop(r0); // value
+ frame->Pop(r0); // value
// Setup the name register.
Handle<String> name(GetName());
__ mov(r2, Operand(name));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
- __ push(r0);
+ frame->Push(r0);
break;
}
@@ -3344,10 +3375,10 @@
Property* property = expression_->AsProperty();
ASSERT(property != NULL);
__ RecordPosition(property->position());
- __ pop(r0); // value
+ frame->Pop(r0); // value
SetPropertyStub stub;
__ CallStub(&stub);
- __ push(r0);
+ frame->Push(r0);
break;
}
« no previous file with comments | « src/codegen-arm.h ('k') | src/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698