Emit pushes and pops through the virtual frame on ARM. Merging of
frames is not yet handled. The ARM code generator should be back in line with the IA32 one. Review URL: http://codereview.chromium.org/9182 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@706 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a6554f8785
commit
bdb896cc40
File diff suppressed because it is too large
Load Diff
@ -49,6 +49,11 @@ class VirtualFrame BASE_EMBEDDED {
|
||||
public:
|
||||
explicit VirtualFrame(CodeGenerator* cgen);
|
||||
|
||||
void Enter();
|
||||
void Exit();
|
||||
|
||||
void AllocateLocals();
|
||||
|
||||
MemOperand Top() const { return MemOperand(sp, 0); }
|
||||
|
||||
MemOperand Element(int index) const {
|
||||
@ -70,6 +75,13 @@ class VirtualFrame BASE_EMBEDDED {
|
||||
return MemOperand(fp, (1 + parameter_count_ - index) * kPointerSize);
|
||||
}
|
||||
|
||||
inline void Drop(int count);
|
||||
|
||||
inline void Pop();
|
||||
inline void Pop(Register reg);
|
||||
|
||||
inline void Push(Register reg);
|
||||
|
||||
private:
|
||||
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
|
||||
static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
|
||||
@ -195,6 +207,8 @@ class CodeGenerator: public Visitor {
|
||||
// Accessors
|
||||
MacroAssembler* masm() { return masm_; }
|
||||
|
||||
VirtualFrame* frame() const { return frame_; }
|
||||
|
||||
CodeGenState* state() { return state_; }
|
||||
void set_state(CodeGenState* state) { state_ = state; }
|
||||
|
||||
@ -366,11 +380,6 @@ class CodeGenerator: public Visitor {
|
||||
// should be generated or not.
|
||||
void RecordStatementPosition(Node* node);
|
||||
|
||||
// Activation frames.
|
||||
void EnterJSFrame();
|
||||
void ExitJSFrame();
|
||||
|
||||
|
||||
bool is_eval_; // Tells whether code is generated for eval.
|
||||
Handle<Script> script_;
|
||||
List<DeferredCode*> deferred_;
|
||||
|
@ -99,9 +99,7 @@ void VirtualFrame::Drop(int count) {
|
||||
}
|
||||
|
||||
|
||||
void VirtualFrame::Pop() {
|
||||
__ add(Operand(esp), Immediate(kPointerSize));
|
||||
}
|
||||
void VirtualFrame::Pop() { Drop(1); }
|
||||
|
||||
|
||||
void VirtualFrame::Pop(Register reg) {
|
||||
@ -267,10 +265,8 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
|
||||
__ int3();
|
||||
__ bind(&verified_true);
|
||||
}
|
||||
|
||||
// Update context local.
|
||||
__ mov(frame_->Context(), esi);
|
||||
// Restore the arguments array pointer, if any.
|
||||
}
|
||||
|
||||
// TODO(1241774): Improve this code:
|
||||
@ -310,10 +306,10 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
|
||||
// This section stores the pointer to the arguments object that
|
||||
// was allocated and copied into above. If the address was not
|
||||
// saved to TOS, we push ecx onto the stack.
|
||||
|
||||
// Store the arguments object.
|
||||
// This must happen after context initialization because
|
||||
// the arguments object 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 (arguments_object_allocated) {
|
||||
ASSERT(scope_->arguments() != NULL);
|
||||
ASSERT(scope_->arguments_shadow() != NULL);
|
||||
@ -341,18 +337,17 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
|
||||
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(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;
|
||||
}
|
||||
|
||||
@ -448,10 +443,11 @@ Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
|
||||
|
||||
|
||||
// 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'.
|
||||
// (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,
|
||||
@ -463,6 +459,14 @@ void CodeGenerator::LoadCondition(Expression* x,
|
||||
Visit(x);
|
||||
}
|
||||
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);
|
||||
@ -476,7 +480,6 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
|
||||
|
||||
if (has_cc()) {
|
||||
// convert cc_reg_ into a bool
|
||||
|
||||
Label loaded, materialize_true;
|
||||
__ j(cc_reg_, &materialize_true);
|
||||
frame_->Push(Immediate(Factory::false_value()));
|
||||
@ -663,7 +666,7 @@ void CodeGenerator::ToBoolean(Label* true_target, Label* false_target) {
|
||||
frame_->Push(eax); // Undo the pop(eax) from above.
|
||||
ToBooleanStub stub;
|
||||
__ CallStub(&stub);
|
||||
// Convert result (eax) to condition code.
|
||||
// Convert the result (eax) to condition code.
|
||||
__ test(eax, Operand(eax));
|
||||
|
||||
ASSERT(not_equal == not_zero);
|
||||
@ -2198,7 +2201,6 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
|
||||
frame_->Pop(Operand::StaticVariable(handler_address));
|
||||
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
|
||||
// Next_sp popped.
|
||||
// Preserve the TOS in a register across stack manipulation.
|
||||
frame_->Push(eax);
|
||||
|
||||
// --- Finally block ---
|
||||
|
Loading…
Reference in New Issue
Block a user