Remove variable rewrites and the unneccesary Slot class.

R=fschneider@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/7824038

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9162 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 296612c1
This diff is collapsed.
...@@ -198,14 +198,14 @@ bool LCodeGen::GeneratePrologue() { ...@@ -198,14 +198,14 @@ bool LCodeGen::GeneratePrologue() {
// Copy any necessary parameters into the context. // Copy any necessary parameters into the context.
int num_parameters = scope()->num_parameters(); int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) { for (int i = 0; i < num_parameters; i++) {
Slot* slot = scope()->parameter(i)->AsSlot(); Variable* var = scope()->parameter(i);
if (slot != NULL && slot->type() == Slot::CONTEXT) { if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset + int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize; (num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack. // Load parameter from stack.
__ ldr(r0, MemOperand(fp, parameter_offset)); __ ldr(r0, MemOperand(fp, parameter_offset));
// Store it in the context. // Store it in the context.
__ mov(r1, Operand(Context::SlotOffset(slot->index()))); __ mov(r1, Operand(Context::SlotOffset(var->index())));
__ str(r0, MemOperand(cp, r1)); __ str(r0, MemOperand(cp, r1));
// Update the write barrier. This clobbers all involved // Update the write barrier. This clobbers all involved
// registers, so we have to use two more registers to avoid // registers, so we have to use two more registers to avoid
......
...@@ -39,8 +39,6 @@ namespace internal { ...@@ -39,8 +39,6 @@ namespace internal {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// All the Accept member functions for each syntax tree node type. // All the Accept member functions for each syntax tree node type.
void Slot::Accept(AstVisitor* v) { v->VisitSlot(this); }
#define DECL_ACCEPT(type) \ #define DECL_ACCEPT(type) \
void type::Accept(AstVisitor* v) { v->Visit##type(this); } void type::Accept(AstVisitor* v) { v->Visit##type(this); }
AST_NODE_LIST(DECL_ACCEPT) AST_NODE_LIST(DECL_ACCEPT)
...@@ -396,12 +394,6 @@ bool TargetCollector::IsInlineable() const { ...@@ -396,12 +394,6 @@ bool TargetCollector::IsInlineable() const {
} }
bool Slot::IsInlineable() const {
UNREACHABLE();
return false;
}
bool ForInStatement::IsInlineable() const { bool ForInStatement::IsInlineable() const {
return false; return false;
} }
...@@ -542,7 +534,7 @@ bool Conditional::IsInlineable() const { ...@@ -542,7 +534,7 @@ bool Conditional::IsInlineable() const {
bool VariableProxy::IsInlineable() const { bool VariableProxy::IsInlineable() const {
return var()->is_global() || var()->IsStackAllocated(); return var()->IsUnallocated() || var()->IsStackAllocated();
} }
......
...@@ -165,7 +165,6 @@ class AstNode: public ZoneObject { ...@@ -165,7 +165,6 @@ class AstNode: public ZoneObject {
virtual BreakableStatement* AsBreakableStatement() { return NULL; } virtual BreakableStatement* AsBreakableStatement() { return NULL; }
virtual IterationStatement* AsIterationStatement() { return NULL; } virtual IterationStatement* AsIterationStatement() { return NULL; }
virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; } virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }
virtual Slot* AsSlot() { return NULL; }
// True if the node is simple enough for us to inline calls containing it. // True if the node is simple enough for us to inline calls containing it.
virtual bool IsInlineable() const = 0; virtual bool IsInlineable() const = 0;
...@@ -1112,9 +1111,6 @@ class VariableProxy: public Expression { ...@@ -1112,9 +1111,6 @@ class VariableProxy: public Expression {
DECLARE_NODE_TYPE(VariableProxy) DECLARE_NODE_TYPE(VariableProxy)
// Type testing & conversion
Variable* AsVariable() { return (this == NULL) ? NULL : var_; }
virtual bool IsValidLeftHandSide() { virtual bool IsValidLeftHandSide() {
return var_ == NULL ? true : var_->IsValidLeftHandSide(); return var_ == NULL ? true : var_->IsValidLeftHandSide();
} }
...@@ -1131,10 +1127,7 @@ class VariableProxy: public Expression { ...@@ -1131,10 +1127,7 @@ class VariableProxy: public Expression {
return !is_this() && name().is_identical_to(n); return !is_this() && name().is_identical_to(n);
} }
bool IsArguments() { bool IsArguments() { return var_ != NULL && var_->is_arguments(); }
Variable* variable = AsVariable();
return (variable == NULL) ? false : variable->is_arguments();
}
Handle<String> name() const { return name_; } Handle<String> name() const { return name_; }
Variable* var() const { return var_; } Variable* var() const { return var_; }
...@@ -1165,55 +1158,6 @@ class VariableProxy: public Expression { ...@@ -1165,55 +1158,6 @@ class VariableProxy: public Expression {
}; };
class Slot: public Expression {
public:
enum Type {
// A slot in the parameter section on the stack. index() is
// the parameter index, counting left-to-right, starting at 0.
PARAMETER,
// A slot in the local section on the stack. index() is
// the variable index in the stack frame, starting at 0.
LOCAL,
// An indexed slot in a heap context. index() is the
// variable index in the context object on the heap,
// starting at 0. var()->scope() is the corresponding
// scope.
CONTEXT,
// A named slot in a heap context. var()->name() is the
// variable name in the context object on the heap,
// with lookup starting at the current context. index()
// is invalid.
LOOKUP
};
Slot(Isolate* isolate, Variable* var, Type type, int index)
: Expression(isolate), var_(var), type_(type), index_(index) {
ASSERT(var != NULL);
}
virtual void Accept(AstVisitor* v);
virtual Slot* AsSlot() { return this; }
bool IsStackAllocated() { return type_ == PARAMETER || type_ == LOCAL; }
// Accessors
Variable* var() const { return var_; }
Type type() const { return type_; }
int index() const { return index_; }
bool is_arguments() const { return var_->is_arguments(); }
virtual bool IsInlineable() const;
private:
Variable* var_;
Type type_;
int index_;
};
class Property: public Expression { class Property: public Expression {
public: public:
Property(Isolate* isolate, Property(Isolate* isolate,
...@@ -2194,9 +2138,6 @@ class AstVisitor BASE_EMBEDDED { ...@@ -2194,9 +2138,6 @@ class AstVisitor BASE_EMBEDDED {
void SetStackOverflow() { stack_overflow_ = true; } void SetStackOverflow() { stack_overflow_ = true; }
void ClearStackOverflow() { stack_overflow_ = false; } void ClearStackOverflow() { stack_overflow_ = false; }
// Nodes not appearing in the AST, including slots.
virtual void VisitSlot(Slot* node) { UNREACHABLE(); }
// Individual AST nodes. // Individual AST nodes.
#define DEF_VISIT(type) \ #define DEF_VISIT(type) \
virtual void Visit##type(type* node) = 0; virtual void Visit##type(type* node) = 0;
......
...@@ -190,9 +190,9 @@ void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -190,9 +190,9 @@ void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
void BreakableStatementChecker::VisitAssignment(Assignment* expr) { void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
// If assigning to a property (including a global property) the assignment is // If assigning to a property (including a global property) the assignment is
// breakable. // breakable.
Variable* var = expr->target()->AsVariableProxy()->AsVariable(); VariableProxy* proxy = expr->target()->AsVariableProxy();
Property* prop = expr->target()->AsProperty(); Property* prop = expr->target()->AsProperty();
if (prop != NULL || (var != NULL && var->is_global())) { if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
is_breakable_ = true; is_breakable_ = true;
return; return;
} }
...@@ -395,26 +395,6 @@ void FullCodeGenerator::RecordStackCheck(int ast_id) { ...@@ -395,26 +395,6 @@ void FullCodeGenerator::RecordStackCheck(int ast_id) {
} }
int FullCodeGenerator::SlotOffset(Slot* slot) {
ASSERT(slot != NULL);
// Offset is negative because higher indexes are at lower addresses.
int offset = -slot->index() * kPointerSize;
// Adjust by a (parameter or local) base offset.
switch (slot->type()) {
case Slot::PARAMETER:
offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
break;
case Slot::LOCAL:
offset += JavaScriptFrameConstants::kLocal0Offset;
break;
case Slot::CONTEXT:
case Slot::LOOKUP:
UNREACHABLE();
}
return offset;
}
bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) { bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
// Inline smi case inside loops, but not division and modulo which // Inline smi case inside loops, but not division and modulo which
// are too complicated and take up too much space. // are too complicated and take up too much space.
...@@ -529,34 +509,21 @@ void FullCodeGenerator::DoTest(const TestContext* context) { ...@@ -529,34 +509,21 @@ void FullCodeGenerator::DoTest(const TestContext* context) {
void FullCodeGenerator::VisitDeclarations( void FullCodeGenerator::VisitDeclarations(
ZoneList<Declaration*>* declarations) { ZoneList<Declaration*>* declarations) {
int length = declarations->length(); int length = declarations->length();
int globals = 0; int global_count = 0;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
Declaration* decl = declarations->at(i); Declaration* decl = declarations->at(i);
Variable* var = decl->proxy()->var(); EmitDeclaration(decl->proxy(), decl->mode(), decl->fun(), &global_count);
Slot* slot = var->AsSlot();
// If it was not possible to allocate the variable at compile
// time, we need to "declare" it at runtime to make sure it
// actually exists in the local context.
if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
VisitDeclaration(decl);
} else {
// Count global variables and functions for later processing
globals++;
}
} }
// Compute array of global variable and function declarations. // Batch declare global functions and variables.
// Do nothing in case of no declared global functions or variables. if (global_count > 0) {
if (globals > 0) {
Handle<FixedArray> array = Handle<FixedArray> array =
isolate()->factory()->NewFixedArray(2 * globals, TENURED); isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
for (int j = 0, i = 0; i < length; i++) { for (int j = 0, i = 0; i < length; i++) {
Declaration* decl = declarations->at(i); Declaration* decl = declarations->at(i);
Variable* var = decl->proxy()->var(); Variable* var = decl->proxy()->var();
Slot* slot = var->AsSlot();
if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) { if (var->IsUnallocated()) {
array->set(j++, *(var->name())); array->set(j++, *(var->name()));
if (decl->fun() == NULL) { if (decl->fun() == NULL) {
if (var->mode() == Variable::CONST) { if (var->mode() == Variable::CONST) {
...@@ -578,7 +545,7 @@ void FullCodeGenerator::VisitDeclarations( ...@@ -578,7 +545,7 @@ void FullCodeGenerator::VisitDeclarations(
} }
} }
// Invoke the platform-dependent code generator to do the actual // Invoke the platform-dependent code generator to do the actual
// declaration the global variables and functions. // declaration the global functions and variables.
DeclareGlobals(array); DeclareGlobals(array);
} }
} }
......
...@@ -304,10 +304,6 @@ class FullCodeGenerator: public AstVisitor { ...@@ -304,10 +304,6 @@ class FullCodeGenerator: public AstVisitor {
// with a GC-safe value. // with a GC-safe value.
void ClearAccumulator(); void ClearAccumulator();
// Compute the frame pointer relative offset for a given local or
// parameter slot.
int SlotOffset(Slot* slot);
// Determine whether or not to inline the smi case for the given // Determine whether or not to inline the smi case for the given
// operation. // operation.
bool ShouldInlineSmiCase(Token::Value op); bool ShouldInlineSmiCase(Token::Value op);
...@@ -337,13 +333,29 @@ class FullCodeGenerator: public AstVisitor { ...@@ -337,13 +333,29 @@ class FullCodeGenerator: public AstVisitor {
Label* fall_through); Label* fall_through);
#endif // V8_TARGET_ARCH_MIPS #endif // V8_TARGET_ARCH_MIPS
void Move(Slot* dst, Register source, Register scratch1, Register scratch2); // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into
void Move(Register dst, Slot* source); // a register. Emits a context chain walk if if necessary (so does
// SetVar) so avoid calling both on the same variable.
// Return an operand used to read/write to a known (ie, non-LOOKUP) slot. void GetVar(Register destination, Variable* var);
// May emit code to traverse the context chain, destroying the scratch
// register. // Assign to a known (PARAMETER, LOCAL, or CONTEXT) variable. If it's in
MemOperand EmitSlotSearch(Slot* slot, Register scratch); // the context, the write barrier will be emitted and source, scratch0,
// scratch1 will be clobbered. Emits a context chain walk if if necessary
// (so does GetVar) so avoid calling both on the same variable.
void SetVar(Variable* var,
Register source,
Register scratch0,
Register scratch1);
// An operand used to read/write a stack-allocated (PARAMETER or LOCAL)
// variable. Writing does not need the write barrier.
MemOperand StackOperand(Variable* var);
// An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT)
// variable. May emit code to traverse the context chain, loading the
// found context into the scratch register. Writing to this operand will
// need the write barrier if location is CONTEXT.
MemOperand VarOperand(Variable* var, Register scratch);
// Forward the bailout responsibility for the given expression to // Forward the bailout responsibility for the given expression to
// the next child visited (which must be in a test context). // the next child visited (which must be in a test context).
...@@ -421,7 +433,8 @@ class FullCodeGenerator: public AstVisitor { ...@@ -421,7 +433,8 @@ class FullCodeGenerator: public AstVisitor {
// declaration. Functions have an initial value. // declaration. Functions have an initial value.
void EmitDeclaration(VariableProxy* proxy, void EmitDeclaration(VariableProxy* proxy,
Variable::Mode mode, Variable::Mode mode,
FunctionLiteral* function); FunctionLiteral* function,
int* global_count);
// Platform-specific code for checking the stack limit at the back edge of // Platform-specific code for checking the stack limit at the back edge of
// a loop. // a loop.
...@@ -452,14 +465,14 @@ class FullCodeGenerator: public AstVisitor { ...@@ -452,14 +465,14 @@ class FullCodeGenerator: public AstVisitor {
#undef EMIT_INLINE_RUNTIME_CALL #undef EMIT_INLINE_RUNTIME_CALL
// Platform-specific code for loading variables. // Platform-specific code for loading variables.
void EmitLoadGlobalSlotCheckExtensions(Slot* slot, void EmitLoadGlobalCheckExtensions(Variable* var,
TypeofState typeof_state, TypeofState typeof_state,
Label* slow); Label* slow);
MemOperand ContextSlotOperandCheckExtensions(Slot* slot, Label* slow); MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow);
void EmitDynamicLoadFromSlotFastCase(Slot* slot, void EmitDynamicLookupFastCase(Variable* var,
TypeofState typeof_state, TypeofState typeof_state,
Label* slow, Label* slow,
Label* done); Label* done);
void EmitVariableLoad(VariableProxy* proxy); void EmitVariableLoad(VariableProxy* proxy);
enum ResolveEvalFlag { enum ResolveEvalFlag {
...@@ -636,11 +649,11 @@ class FullCodeGenerator: public AstVisitor { ...@@ -636,11 +649,11 @@ class FullCodeGenerator: public AstVisitor {
// this expression context. // this expression context.
virtual void Plug(bool flag) const = 0; virtual void Plug(bool flag) const = 0;
// Emit code to convert a pure value (in a register, slot, as a literal, // Emit code to convert a pure value (in a register, known variable
// or on top of the stack) into the result expected according to this // location, as a literal, or on top of the stack) into the result
// expression context. // expected according to this expression context.
virtual void Plug(Register reg) const = 0; virtual void Plug(Register reg) const = 0;
virtual void Plug(Slot* slot) const = 0; virtual void Plug(Variable* var) const = 0;
virtual void Plug(Handle<Object> lit) const = 0; virtual void Plug(Handle<Object> lit) const = 0;
virtual void Plug(Heap::RootListIndex index) const = 0; virtual void Plug(Heap::RootListIndex index) const = 0;
virtual void PlugTOS() const = 0; virtual void PlugTOS() const = 0;
...@@ -698,7 +711,7 @@ class FullCodeGenerator: public AstVisitor { ...@@ -698,7 +711,7 @@ class FullCodeGenerator: public AstVisitor {
virtual void Plug(bool flag) const; virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const; virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const; virtual void Plug(Label* materialize_true, Label* materialize_false) const;
virtual void Plug(Slot* slot) const; virtual void Plug(Variable* var) const;
virtual void Plug(Handle<Object> lit) const; virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const; virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const; virtual void PlugTOS() const;
...@@ -721,7 +734,7 @@ class FullCodeGenerator: public AstVisitor { ...@@ -721,7 +734,7 @@ class FullCodeGenerator: public AstVisitor {
virtual void Plug(bool flag) const; virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const; virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const; virtual void Plug(Label* materialize_true, Label* materialize_false) const;
virtual void Plug(Slot* slot) const; virtual void Plug(Variable* var) const;
virtual void Plug(Handle<Object> lit) const; virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const; virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const; virtual void PlugTOS() const;
...@@ -762,7 +775,7 @@ class FullCodeGenerator: public AstVisitor { ...@@ -762,7 +775,7 @@ class FullCodeGenerator: public AstVisitor {
virtual void Plug(bool flag) const; virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const; virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const; virtual void Plug(Label* materialize_true, Label* materialize_false) const;
virtual void Plug(Slot* slot) const; virtual void Plug(Variable* var) const;
virtual void Plug(Handle<Object> lit) const; virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const; virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const; virtual void PlugTOS() const;
...@@ -792,7 +805,7 @@ class FullCodeGenerator: public AstVisitor { ...@@ -792,7 +805,7 @@ class FullCodeGenerator: public AstVisitor {
virtual void Plug(bool flag) const; virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const; virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const; virtual void Plug(Label* materialize_true, Label* materialize_false) const;
virtual void Plug(Slot* slot) const; virtual void Plug(Variable* var) const;
virtual void Plug(Handle<Object> lit) const; virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const; virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const; virtual void PlugTOS() const;
......
This diff is collapsed.
...@@ -455,12 +455,11 @@ class HEnvironment: public ZoneObject { ...@@ -455,12 +455,11 @@ class HEnvironment: public ZoneObject {
// by 1 (receiver is parameter index -1 but environment index 0). // by 1 (receiver is parameter index -1 but environment index 0).
// Stack-allocated local indices are shifted by the number of parameters. // Stack-allocated local indices are shifted by the number of parameters.
int IndexFor(Variable* variable) const { int IndexFor(Variable* variable) const {
Slot* slot = variable->AsSlot(); ASSERT(variable->IsStackAllocated());
ASSERT(slot != NULL && slot->IsStackAllocated()); int shift = variable->IsParameter()
int shift = (slot->type() == Slot::PARAMETER)
? 1 ? 1
: parameter_count_ + specials_count_; : parameter_count_ + specials_count_;
return slot->index() + shift; return variable->index() + shift;
} }
Handle<JSFunction> closure_; Handle<JSFunction> closure_;
......
This diff is collapsed.
...@@ -194,14 +194,14 @@ bool LCodeGen::GeneratePrologue() { ...@@ -194,14 +194,14 @@ bool LCodeGen::GeneratePrologue() {
// Copy parameters into context if necessary. // Copy parameters into context if necessary.
int num_parameters = scope()->num_parameters(); int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) { for (int i = 0; i < num_parameters; i++) {
Slot* slot = scope()->parameter(i)->AsSlot(); Variable* var = scope()->parameter(i);
if (slot != NULL && slot->type() == Slot::CONTEXT) { if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset + int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize; (num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack. // Load parameter from stack.
__ mov(eax, Operand(ebp, parameter_offset)); __ mov(eax, Operand(ebp, parameter_offset));
// Store it in the context. // Store it in the context.
int context_offset = Context::SlotOffset(slot->index()); int context_offset = Context::SlotOffset(var->index());
__ mov(Operand(esi, context_offset), eax); __ mov(Operand(esi, context_offset), eax);
// Update the write barrier. This clobbers all involved // Update the write barrier. This clobbers all involved
// registers, so we have to use a third register to avoid // registers, so we have to use a third register to avoid
......
...@@ -860,8 +860,7 @@ class FunctionInfoListener { ...@@ -860,8 +860,7 @@ class FunctionInfoListener {
int j = 0; int j = 0;
for (int i = 0; i < list.length(); i++) { for (int i = 0; i < list.length(); i++) {
Variable* var1 = list[i]; Variable* var1 = list[i];
Slot* slot = var1->AsSlot(); if (var1->IsContextSlot()) {
if (slot != NULL && slot->type() == Slot::CONTEXT) {
if (j != i) { if (j != i) {
list[j] = var1; list[j] = var1;
} }
...@@ -873,7 +872,7 @@ class FunctionInfoListener { ...@@ -873,7 +872,7 @@ class FunctionInfoListener {
for (int k = 1; k < j; k++) { for (int k = 1; k < j; k++) {
int l = k; int l = k;
for (int m = k + 1; m < j; m++) { for (int m = k + 1; m < j; m++) {
if (list[l]->AsSlot()->index() > list[m]->AsSlot()->index()) { if (list[l]->index() > list[m]->index()) {
l = m; l = m;
} }
} }
...@@ -887,7 +886,7 @@ class FunctionInfoListener { ...@@ -887,7 +886,7 @@ class FunctionInfoListener {
SetElementNonStrict( SetElementNonStrict(
scope_info_list, scope_info_list,
scope_info_length, scope_info_length,
Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index()))); Handle<Smi>(Smi::FromInt(list[i]->index())));
scope_info_length++; scope_info_length++;
} }
SetElementNonStrict(scope_info_list, SetElementNonStrict(scope_info_list,
......
...@@ -200,7 +200,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { ...@@ -200,7 +200,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// Copy any necessary parameters into the context. // Copy any necessary parameters into the context.
int num_parameters = info->scope()->num_parameters(); int num_parameters = info->scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) { for (int i = 0; i < num_parameters; i++) {
Slot* slot = scope()->parameter(i)->AsSlot(); Slot* slot = scope()->parameter(i)->rewrite();
if (slot != NULL && slot->type() == Slot::CONTEXT) { if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset + int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize; (num_parameters - 1 - i) * kPointerSize;
...@@ -252,7 +252,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { ...@@ -252,7 +252,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
ArgumentsAccessStub stub(type); ArgumentsAccessStub stub(type);
__ CallStub(&stub); __ CallStub(&stub);
Move(arguments->AsSlot(), v0, a1, a2); Move(arguments->rewrite(), v0, a1, a2);
} }
if (FLAG_trace) { if (FLAG_trace) {
...@@ -633,6 +633,7 @@ MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { ...@@ -633,6 +633,7 @@ MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
return ContextOperand(scratch, slot->index()); return ContextOperand(scratch, slot->index());
} }
case Slot::LOOKUP: case Slot::LOOKUP:
case Slot::GLOBAL:
UNREACHABLE(); UNREACHABLE();
} }
UNREACHABLE(); UNREACHABLE();
...@@ -697,7 +698,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, ...@@ -697,7 +698,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
Comment cmnt(masm_, "[ Declaration"); Comment cmnt(masm_, "[ Declaration");
Variable* variable = proxy->var(); Variable* variable = proxy->var();
ASSERT(variable != NULL); // Must have been resolved. ASSERT(variable != NULL); // Must have been resolved.
Slot* slot = variable->AsSlot(); Slot* slot = variable->rewrite();
ASSERT(slot != NULL); ASSERT(slot != NULL);
switch (slot->type()) { switch (slot->type()) {
case Slot::PARAMETER: case Slot::PARAMETER:
...@@ -772,6 +773,9 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, ...@@ -772,6 +773,9 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
__ CallRuntime(Runtime::kDeclareContextSlot, 4); __ CallRuntime(Runtime::kDeclareContextSlot, 4);
break; break;
} }
case Slot::GLOBAL:
UNREACHABLE();
} }
} }
...@@ -1192,7 +1196,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( ...@@ -1192,7 +1196,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
__ Branch(done); __ Branch(done);
} else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); Slot* potential_slot = slot->var()->local_if_not_shadowed()->rewrite();
Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
if (potential_slot != NULL) { if (potential_slot != NULL) {
// Generate fast case for locals that rewrite to slots. // Generate fast case for locals that rewrite to slots.
...@@ -1218,7 +1222,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( ...@@ -1218,7 +1222,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
// variables. Then load the argument from the arguments // variables. Then load the argument from the arguments
// object using keyed load. // object using keyed load.
__ lw(a1, __ lw(a1,
ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), ContextSlotOperandCheckExtensions(obj_proxy->var()->rewrite(),
slow)); slow));
__ li(a0, Operand(key_literal->handle())); __ li(a0, Operand(key_literal->handle()));
Handle<Code> ic = Handle<Code> ic =
...@@ -1239,7 +1243,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { ...@@ -1239,7 +1243,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
// Three cases: non-this global variables, lookup slots, and all other // Three cases: non-this global variables, lookup slots, and all other
// types of slots. // types of slots.
Slot* slot = var->AsSlot(); Slot* slot = var->rewrite();
ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
if (slot == NULL) { if (slot == NULL) {
...@@ -1836,7 +1840,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { ...@@ -1836,7 +1840,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var, void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) { Token::Value op) {
ASSERT(var != NULL); ASSERT(var != NULL);
ASSERT(var->is_global() || var->AsSlot() != NULL); ASSERT(var->is_global() || var->rewrite() != NULL);
if (var->is_global()) { if (var->is_global()) {
ASSERT(!var->is_this()); ASSERT(!var->is_this());
...@@ -1856,7 +1860,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, ...@@ -1856,7 +1860,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// scope. However, unlike var initializers, const initializers are able // scope. However, unlike var initializers, const initializers are able
// to drill a hole to that function context, even from inside a 'with' // to drill a hole to that function context, even from inside a 'with'
// context. We thus bypass the normal static scope lookup. // context. We thus bypass the normal static scope lookup.
Slot* slot = var->AsSlot(); Slot* slot = var->rewrite();
Label skip; Label skip;
switch (slot->type()) { switch (slot->type()) {
case Slot::PARAMETER: case Slot::PARAMETER:
...@@ -1877,6 +1881,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, ...@@ -1877,6 +1881,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ Push(cp, a0); // Context and name. __ Push(cp, a0); // Context and name.
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3); __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
break; break;
case Slot::GLOBAL:
UNREACHABLE();
} }
__ bind(&skip); __ bind(&skip);
} else if (var->mode() == Variable::LET && op != Token::INIT_LET) { } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
...@@ -1933,7 +1939,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, ...@@ -1933,7 +1939,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
} else if (var->mode() != Variable::CONST) { } else if (var->mode() != Variable::CONST) {
// Perform the assignment for non-const variables. Const assignments // Perform the assignment for non-const variables. Const assignments
// are simply skipped. // are simply skipped.
Slot* slot = var->AsSlot(); Slot* slot = var->rewrite();
switch (slot->type()) { switch (slot->type()) {
case Slot::PARAMETER: case Slot::PARAMETER:
case Slot::LOCAL: case Slot::LOCAL:
...@@ -1960,6 +1966,9 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, ...@@ -1960,6 +1966,9 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ Push(cp, a1, a0); // Context, name, strict mode. __ Push(cp, a1, a0); // Context, name, strict mode.
__ CallRuntime(Runtime::kStoreContextSlot, 4); __ CallRuntime(Runtime::kStoreContextSlot, 4);
break; break;
case Slot::GLOBAL:
UNREACHABLE();
} }
} }
} }
...@@ -2227,9 +2236,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { ...@@ -2227,9 +2236,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// in generated code. If we succeed, there is no need to perform a // in generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system. // context lookup in the runtime system.
Label done; Label done;
if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { if (var->rewrite() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
Label slow; Label slow;
EmitLoadGlobalSlotCheckExtensions(var->AsSlot(), EmitLoadGlobalSlotCheckExtensions(var->rewrite(),
NOT_INSIDE_TYPEOF, NOT_INSIDE_TYPEOF,
&slow); &slow);
// Push the function and resolve eval. // Push the function and resolve eval.
...@@ -2267,15 +2276,15 @@ void FullCodeGenerator::VisitCall(Call* expr) { ...@@ -2267,15 +2276,15 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ lw(a0, GlobalObjectOperand()); __ lw(a0, GlobalObjectOperand());
__ push(a0); __ push(a0);
EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
} else if (var != NULL && var->AsSlot() != NULL && } else if (var != NULL && var->rewrite() != NULL &&
var->AsSlot()->type() == Slot::LOOKUP) { var->rewrite()->type() == Slot::LOOKUP) {
// Call to a lookup slot (dynamically introduced variable). // Call to a lookup slot (dynamically introduced variable).
Label slow, done; Label slow, done;
{ PreservePositionScope scope(masm()->positions_recorder()); { PreservePositionScope scope(masm()->positions_recorder());
// Generate code for loading from variables potentially shadowed // Generate code for loading from variables potentially shadowed
// by eval-introduced variables. // by eval-introduced variables.
EmitDynamicLoadFromSlotFastCase(var->AsSlot(), EmitDynamicLoadFromSlotFastCase(var->rewrite(),
NOT_INSIDE_TYPEOF, NOT_INSIDE_TYPEOF,
&slow, &slow,
&done); &done);
...@@ -3680,8 +3689,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { ...@@ -3680,8 +3689,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
__ Push(a2, a1, a0); __ Push(a2, a1, a0);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(v0); context()->Plug(v0);
} else if (var->AsSlot() != NULL && } else if (var->rewrite() != NULL &&
var->AsSlot()->type() != Slot::LOOKUP) { var->rewrite()->type() != Slot::LOOKUP) {
// Result of deleting non-global, non-dynamic variables is false. // Result of deleting non-global, non-dynamic variables is false.
// The subexpression does not have side effects. // The subexpression does not have side effects.
context()->Plug(false); context()->Plug(false);
...@@ -3971,13 +3980,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { ...@@ -3971,13 +3980,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
PrepareForBailout(expr, TOS_REG); PrepareForBailout(expr, TOS_REG);
context()->Plug(v0); context()->Plug(v0);
} else if (proxy != NULL && } else if (proxy != NULL &&
proxy->var()->AsSlot() != NULL && proxy->var()->rewrite() != NULL &&
proxy->var()->AsSlot()->type() == Slot::LOOKUP) { proxy->var()->rewrite()->type() == Slot::LOOKUP) {
Label done, slow; Label done, slow;
// Generate code for loading from variables potentially shadowed // Generate code for loading from variables potentially shadowed
// by eval-introduced variables. // by eval-introduced variables.
Slot* slot = proxy->var()->AsSlot(); Slot* slot = proxy->var()->rewrite();
EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
__ bind(&slow); __ bind(&slow);
......
...@@ -284,28 +284,6 @@ void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) { ...@@ -284,28 +284,6 @@ void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
} }
void PrettyPrinter::VisitSlot(Slot* node) {
switch (node->type()) {
case Slot::PARAMETER:
Print("parameter[%d]", node->index());
break;
case Slot::LOCAL:
Print("local[%d]", node->index());
break;
case Slot::CONTEXT:
Print("context[%d]", node->index());
break;
case Slot::LOOKUP:
Print("lookup[");
PrintLiteral(node->var()->name(), false);
Print("]");
break;
default:
UNREACHABLE();
}
}
void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
PrintLiteral(node->name(), false); PrintLiteral(node->name(), false);
} }
...@@ -751,7 +729,7 @@ void AstPrinter::VisitDeclaration(Declaration* node) { ...@@ -751,7 +729,7 @@ void AstPrinter::VisitDeclaration(Declaration* node) {
if (node->fun() == NULL) { if (node->fun() == NULL) {
// var or const declarations // var or const declarations
PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()), PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
node->proxy()->AsVariable(), node->proxy()->var(),
node->proxy()->name()); node->proxy()->name());
} else { } else {
// function declarations // function declarations
...@@ -959,19 +937,26 @@ void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) { ...@@ -959,19 +937,26 @@ void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
} }
void AstPrinter::VisitSlot(Slot* node) {
PrintIndented("SLOT ");
PrettyPrinter::VisitSlot(node);
Print("\n");
}
void AstPrinter::VisitVariableProxy(VariableProxy* node) { void AstPrinter::VisitVariableProxy(VariableProxy* node) {
PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name());
Variable* var = node->var(); Variable* var = node->var();
if (var != NULL && var->rewrite() != NULL) { PrintLiteralWithModeIndented("VAR PROXY", var, node->name());
IndentedScope indent(this); { IndentedScope indent(this);
Visit(var->rewrite()); switch (var->location()) {
case Variable::UNALLOCATED:
break;
case Variable::PARAMETER:
Print("parameter[%d]", var->index());
break;
case Variable::LOCAL:
Print("local[%d]", var->index());
break;
case Variable::CONTEXT:
Print("context[%d]", var->index());
break;
case Variable::LOOKUP:
Print("lookup");
break;
}
} }
} }
...@@ -1287,39 +1272,32 @@ void JsonAstBuilder::VisitConditional(Conditional* expr) { ...@@ -1287,39 +1272,32 @@ void JsonAstBuilder::VisitConditional(Conditional* expr) {
} }
void JsonAstBuilder::VisitSlot(Slot* expr) { void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
TagScope tag(this, "Slot"); TagScope tag(this, "Variable");
{ {
AttributesScope attributes(this); AttributesScope attributes(this);
switch (expr->type()) { Variable* var = expr->var();
case Slot::PARAMETER: AddAttribute("name", var->name());
AddAttribute("type", "PARAMETER"); switch (var->location()) {
case Variable::UNALLOCATED:
AddAttribute("location", "UNALLOCATED");
break; break;
case Slot::LOCAL: case Variable::PARAMETER:
AddAttribute("type", "LOCAL"); AddAttribute("location", "PARAMETER");
AddAttribute("index", var->index());
break; break;
case Slot::CONTEXT: case Variable::LOCAL:
AddAttribute("type", "CONTEXT"); AddAttribute("location", "LOCAL");
AddAttribute("index", var->index());
break; break;
case Slot::LOOKUP: case Variable::CONTEXT:
AddAttribute("type", "LOOKUP"); AddAttribute("location", "CONTEXT");
AddAttribute("index", var->index());
break;
case Variable::LOOKUP:
AddAttribute("location", "LOOKUP");
break; break;
} }
AddAttribute("index", expr->index());
}
}
void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
if (expr->var()->rewrite() == NULL) {
TagScope tag(this, "VariableProxy");
{
AttributesScope attributes(this);
AddAttribute("name", expr->name());
AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
}
} else {
Visit(expr->var()->rewrite());
} }
} }
......
...@@ -52,7 +52,6 @@ class PrettyPrinter: public AstVisitor { ...@@ -52,7 +52,6 @@ class PrettyPrinter: public AstVisitor {
// Print a node to stdout. // Print a node to stdout.
static void PrintOut(AstNode* node); static void PrintOut(AstNode* node);
virtual void VisitSlot(Slot* node);
// Individual nodes // Individual nodes
#define DECLARE_VISIT(type) virtual void Visit##type(type* node); #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT) AST_NODE_LIST(DECLARE_VISIT)
...@@ -87,7 +86,6 @@ class AstPrinter: public PrettyPrinter { ...@@ -87,7 +86,6 @@ class AstPrinter: public PrettyPrinter {
const char* PrintProgram(FunctionLiteral* program); const char* PrintProgram(FunctionLiteral* program);
// Individual nodes // Individual nodes
virtual void VisitSlot(Slot* node);
#define DECLARE_VISIT(type) virtual void Visit##type(type* node); #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT) AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT #undef DECLARE_VISIT
...@@ -163,7 +161,6 @@ class JsonAstBuilder: public PrettyPrinter { ...@@ -163,7 +161,6 @@ class JsonAstBuilder: public PrettyPrinter {
void AddAttribute(const char* name, bool value); void AddAttribute(const char* name, bool value);
// AST node visit functions. // AST node visit functions.
virtual void VisitSlot(Slot* node);
#define DECLARE_VISIT(type) virtual void Visit##type(type* node); #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT) AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT #undef DECLARE_VISIT
......
...@@ -39,12 +39,8 @@ namespace internal { ...@@ -39,12 +39,8 @@ namespace internal {
static int CompareLocal(Variable* const* v, Variable* const* w) { static int CompareLocal(Variable* const* v, Variable* const* w) {
Slot* s = (*v)->AsSlot(); int x = (*v)->index();
Slot* t = (*w)->AsSlot(); int y = (*w)->index();
// We may have rewritten parameters (that are in the arguments object)
// and which may have a NULL slot... - find a better solution...
int x = (s != NULL ? s->index() : 0);
int y = (t != NULL ? t->index() : 0);
// Consider sorting them according to type as well? // Consider sorting them according to type as well?
return x - y; return x - y;
} }
...@@ -86,27 +82,24 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) ...@@ -86,27 +82,24 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
for (int i = 0; i < locals.length(); i++) { for (int i = 0; i < locals.length(); i++) {
Variable* var = locals[i]; Variable* var = locals[i];
if (var->is_used()) { if (var->is_used()) {
Slot* slot = var->AsSlot(); switch (var->location()) {
if (slot != NULL) { case Variable::UNALLOCATED:
switch (slot->type()) { case Variable::PARAMETER:
case Slot::PARAMETER: break;
// explicitly added to parameters_ above - ignore
break; case Variable::LOCAL:
ASSERT(stack_slots_.length() == var->index());
case Slot::LOCAL: stack_slots_.Add(var->name());
ASSERT(stack_slots_.length() == slot->index()); break;
stack_slots_.Add(var->name());
break; case Variable::CONTEXT:
heap_locals.Add(var);
case Slot::CONTEXT: break;
heap_locals.Add(var);
break; case Variable::LOOKUP:
// We don't expect lookup variables in the locals list.
case Slot::LOOKUP: UNREACHABLE();
// This is currently not used. break;
UNREACHABLE();
break;
}
} }
} }
} }
...@@ -115,9 +108,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) ...@@ -115,9 +108,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
if (scope->num_heap_slots() > 0) { if (scope->num_heap_slots() > 0) {
// Add user-defined slots. // Add user-defined slots.
for (int i = 0; i < heap_locals.length(); i++) { for (int i = 0; i < heap_locals.length(); i++) {
ASSERT(heap_locals[i]->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS == ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
context_slots_.length()); context_slots_.length());
ASSERT(heap_locals[i]->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS == ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
context_modes_.length()); context_modes_.length());
context_slots_.Add(heap_locals[i]->name()); context_slots_.Add(heap_locals[i]->name());
context_modes_.Add(heap_locals[i]->mode()); context_modes_.Add(heap_locals[i]->mode());
...@@ -140,9 +133,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) ...@@ -140,9 +133,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
// list - instead it must be handled separately in the // list - instead it must be handled separately in the
// Contexts::Lookup() function. Thus record an empty symbol here so we // Contexts::Lookup() function. Thus record an empty symbol here so we
// get the correct number of context slots. // get the correct number of context slots.
ASSERT(proxy->var()->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS == ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
context_slots_.length()); context_slots_.length());
ASSERT(proxy->var()->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS == ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
context_modes_.length()); context_modes_.length());
context_slots_.Add(FACTORY->empty_symbol()); context_slots_.Add(FACTORY->empty_symbol());
context_modes_.Add(Variable::INTERNAL); context_modes_.Add(Variable::INTERNAL);
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "bootstrapper.h" #include "bootstrapper.h"
#include "compiler.h" #include "compiler.h"
#include "prettyprinter.h"
#include "scopeinfo.h" #include "scopeinfo.h"
#include "allocation-inl.h" #include "allocation-inl.h"
...@@ -314,7 +313,7 @@ void Scope::Initialize(bool inside_with) { ...@@ -314,7 +313,7 @@ void Scope::Initialize(bool inside_with) {
Variable::VAR, Variable::VAR,
false, false,
Variable::THIS); Variable::THIS);
var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1)); var->AllocateTo(Variable::PARAMETER, -1);
receiver_ = var; receiver_ = var;
} }
...@@ -389,7 +388,7 @@ Variable* Scope::LocalLookup(Handle<String> name) { ...@@ -389,7 +388,7 @@ Variable* Scope::LocalLookup(Handle<String> name) {
Variable* var = Variable* var =
variables_.Declare(this, name, mode, true, Variable::NORMAL); variables_.Declare(this, name, mode, true, Variable::NORMAL);
var->set_rewrite(NewSlot(var, Slot::CONTEXT, index)); var->AllocateTo(Variable::CONTEXT, index);
return var; return var;
} }
...@@ -410,7 +409,7 @@ Variable* Scope::DeclareFunctionVar(Handle<String> name) { ...@@ -410,7 +409,7 @@ Variable* Scope::DeclareFunctionVar(Handle<String> name) {
Variable* function_var = Variable* function_var =
new Variable(this, name, Variable::CONST, true, Variable::NORMAL); new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var); function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
return function_->var(); return function_var;
} }
...@@ -438,7 +437,8 @@ Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { ...@@ -438,7 +437,8 @@ Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) {
Variable* Scope::DeclareGlobal(Handle<String> name) { Variable* Scope::DeclareGlobal(Handle<String> name) {
ASSERT(is_global_scope()); ASSERT(is_global_scope());
return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL,
true,
Variable::NORMAL); Variable::NORMAL);
} }
...@@ -471,8 +471,11 @@ void Scope::RemoveUnresolved(VariableProxy* var) { ...@@ -471,8 +471,11 @@ void Scope::RemoveUnresolved(VariableProxy* var) {
Variable* Scope::NewTemporary(Handle<String> name) { Variable* Scope::NewTemporary(Handle<String> name) {
ASSERT(!already_resolved()); ASSERT(!already_resolved());
Variable* var = Variable* var = new Variable(this,
new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); name,
Variable::TEMPORARY,
true,
Variable::NORMAL);
temps_.Add(var); temps_.Add(var);
return var; return var;
} }
...@@ -665,17 +668,35 @@ static void PrintName(Handle<String> name) { ...@@ -665,17 +668,35 @@ static void PrintName(Handle<String> name) {
} }
static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) { static void PrintLocation(Variable* var) {
if (var->is_used() || var->rewrite() != NULL) { switch (var->location()) {
case Variable::UNALLOCATED:
break;
case Variable::PARAMETER:
PrintF("parameter[%d]", var->index());
break;
case Variable::LOCAL:
PrintF("local[%d]", var->index());
break;
case Variable::CONTEXT:
PrintF("context[%d]", var->index());
break;
case Variable::LOOKUP:
PrintF("lookup");
break;
}
}
static void PrintVar(int indent, Variable* var) {
if (var->is_used() || !var->IsUnallocated()) {
Indent(indent, Variable::Mode2String(var->mode())); Indent(indent, Variable::Mode2String(var->mode()));
PrintF(" "); PrintF(" ");
PrintName(var->name()); PrintName(var->name());
PrintF("; // "); PrintF("; // ");
if (var->rewrite() != NULL) { PrintLocation(var);
PrintF("%s, ", printer->Print(var->rewrite()));
if (var->is_accessed_from_inner_function_scope()) PrintF(", ");
}
if (var->is_accessed_from_inner_function_scope()) { if (var->is_accessed_from_inner_function_scope()) {
if (!var->IsUnallocated()) PrintF(", ");
PrintF("inner scope access"); PrintF("inner scope access");
} }
PrintF("\n"); PrintF("\n");
...@@ -683,10 +704,10 @@ static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) { ...@@ -683,10 +704,10 @@ static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) {
} }
static void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) { static void PrintMap(int indent, VariableMap* map) {
for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
Variable* var = reinterpret_cast<Variable*>(p->value); Variable* var = reinterpret_cast<Variable*>(p->value);
PrintVar(printer, indent, var); PrintVar(indent, var);
} }
} }
...@@ -743,25 +764,24 @@ void Scope::Print(int n) { ...@@ -743,25 +764,24 @@ void Scope::Print(int n) {
PrintF("%d heap slots\n", num_heap_slots_); } PrintF("%d heap slots\n", num_heap_slots_); }
// Print locals. // Print locals.
PrettyPrinter printer;
Indent(n1, "// function var\n"); Indent(n1, "// function var\n");
if (function_ != NULL) { if (function_ != NULL) {
PrintVar(&printer, n1, function_->var()); PrintVar(n1, function_->var());
} }
Indent(n1, "// temporary vars\n"); Indent(n1, "// temporary vars\n");
for (int i = 0; i < temps_.length(); i++) { for (int i = 0; i < temps_.length(); i++) {
PrintVar(&printer, n1, temps_[i]); PrintVar(n1, temps_[i]);
} }
Indent(n1, "// local vars\n"); Indent(n1, "// local vars\n");
PrintMap(&printer, n1, &variables_); PrintMap(n1, &variables_);
Indent(n1, "// dynamic vars\n"); Indent(n1, "// dynamic vars\n");
if (dynamics_ != NULL) { if (dynamics_ != NULL) {
PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC)); PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC));
PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL)); PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL));
PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL)); PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL));
} }
// Print inner scopes (disable by providing negative n). // Print inner scopes (disable by providing negative n).
...@@ -785,7 +805,7 @@ Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { ...@@ -785,7 +805,7 @@ Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
// Declare a new non-local. // Declare a new non-local.
var = map->Declare(NULL, name, mode, true, Variable::NORMAL); var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
// Allocate it by giving it a dynamic lookup. // Allocate it by giving it a dynamic lookup.
var->set_rewrite(NewSlot(var, Slot::LOOKUP, -1)); var->AllocateTo(Variable::LOOKUP, -1);
} }
return var; return var;
} }
...@@ -1045,12 +1065,12 @@ bool Scope::HasArgumentsParameter() { ...@@ -1045,12 +1065,12 @@ bool Scope::HasArgumentsParameter() {
void Scope::AllocateStackSlot(Variable* var) { void Scope::AllocateStackSlot(Variable* var) {
var->set_rewrite(NewSlot(var, Slot::LOCAL, num_stack_slots_++)); var->AllocateTo(Variable::LOCAL, num_stack_slots_++);
} }
void Scope::AllocateHeapSlot(Variable* var) { void Scope::AllocateHeapSlot(Variable* var) {
var->set_rewrite(NewSlot(var, Slot::CONTEXT, num_heap_slots_++)); var->AllocateTo(Variable::CONTEXT, num_heap_slots_++);
} }
...@@ -1096,14 +1116,14 @@ void Scope::AllocateParameterLocals() { ...@@ -1096,14 +1116,14 @@ void Scope::AllocateParameterLocals() {
if (MustAllocate(var)) { if (MustAllocate(var)) {
if (MustAllocateInContext(var)) { if (MustAllocateInContext(var)) {
ASSERT(var->rewrite() == NULL || var->IsContextSlot()); ASSERT(var->IsUnallocated() || var->IsContextSlot());
if (var->rewrite() == NULL) { if (var->IsUnallocated()) {
AllocateHeapSlot(var); AllocateHeapSlot(var);
} }
} else { } else {
ASSERT(var->rewrite() == NULL || var->IsParameter()); ASSERT(var->IsUnallocated() || var->IsParameter());
if (var->rewrite() == NULL) { if (var->IsUnallocated()) {
var->set_rewrite(NewSlot(var, Slot::PARAMETER, i)); var->AllocateTo(Variable::PARAMETER, i);
} }
} }
} }
...@@ -1113,11 +1133,9 @@ void Scope::AllocateParameterLocals() { ...@@ -1113,11 +1133,9 @@ void Scope::AllocateParameterLocals() {
void Scope::AllocateNonParameterLocal(Variable* var) { void Scope::AllocateNonParameterLocal(Variable* var) {
ASSERT(var->scope() == this); ASSERT(var->scope() == this);
ASSERT(var->rewrite() == NULL || ASSERT(!var->IsVariable(isolate_->factory()->result_symbol()) ||
!var->IsVariable(isolate_->factory()->result_symbol()) || !var->IsStackLocal());
var->AsSlot() == NULL || if (var->IsUnallocated() && MustAllocate(var)) {
var->AsSlot()->type() != Slot::LOCAL);
if (var->rewrite() == NULL && MustAllocate(var)) {
if (MustAllocateInContext(var)) { if (MustAllocateInContext(var)) {
AllocateHeapSlot(var); AllocateHeapSlot(var);
} else { } else {
......
...@@ -444,10 +444,6 @@ class Scope: public ZoneObject { ...@@ -444,10 +444,6 @@ class Scope: public ZoneObject {
// Construct a catch scope with a binding for the name. // Construct a catch scope with a binding for the name.
Scope(Scope* inner_scope, Handle<String> catch_variable_name); Scope(Scope* inner_scope, Handle<String> catch_variable_name);
inline Slot* NewSlot(Variable* var, Slot::Type type, int index) {
return new(isolate_->zone()) Slot(isolate_, var, type, index);
}
void AddInnerScope(Scope* inner_scope) { void AddInnerScope(Scope* inner_scope) {
if (inner_scope != NULL) { if (inner_scope != NULL) {
inner_scopes_.Add(inner_scope); inner_scopes_.Add(inner_scope);
......
...@@ -53,34 +53,6 @@ const char* Variable::Mode2String(Mode mode) { ...@@ -53,34 +53,6 @@ const char* Variable::Mode2String(Mode mode) {
} }
Property* Variable::AsProperty() const {
return rewrite_ == NULL ? NULL : rewrite_->AsProperty();
}
Slot* Variable::AsSlot() const { return rewrite_; }
bool Variable::IsStackAllocated() const {
return rewrite_ != NULL && rewrite_->IsStackAllocated();
}
bool Variable::IsParameter() const {
return rewrite_ != NULL && rewrite_->type() == Slot::PARAMETER;
}
bool Variable::IsStackLocal() const {
return rewrite_ != NULL && rewrite_->type() == Slot::LOCAL;
}
bool Variable::IsContextSlot() const {
return rewrite_ != NULL && rewrite_->type() == Slot::CONTEXT;
}
Variable::Variable(Scope* scope, Variable::Variable(Scope* scope,
Handle<String> name, Handle<String> name,
Mode mode, Mode mode,
...@@ -90,8 +62,9 @@ Variable::Variable(Scope* scope, ...@@ -90,8 +62,9 @@ Variable::Variable(Scope* scope,
name_(name), name_(name),
mode_(mode), mode_(mode),
kind_(kind), kind_(kind),
location_(UNALLOCATED),
index_(-1),
local_if_not_shadowed_(NULL), local_if_not_shadowed_(NULL),
rewrite_(NULL),
is_valid_LHS_(is_valid_LHS), is_valid_LHS_(is_valid_LHS),
is_accessed_from_inner_function_scope_(false), is_accessed_from_inner_function_scope_(false),
is_used_(false) { is_used_(false) {
......
...@@ -74,6 +74,33 @@ class Variable: public ZoneObject { ...@@ -74,6 +74,33 @@ class Variable: public ZoneObject {
ARGUMENTS ARGUMENTS
}; };
enum Location {
// Before and during variable allocation, a variable whose location is
// not yet determined. After allocation, a variable looked up as a
// property on the global object (and possibly absent). name() is the
// variable name, index() is invalid.
UNALLOCATED,
// A slot in the parameter section on the stack. index() is the
// parameter index, counting left-to-right. The reciever is index -1;
// the first parameter is index 0.
PARAMETER,
// A slot in the local section on the stack. index() is the variable
// index in the stack frame, starting at 0.
LOCAL,
// An indexed slot in a heap context. index() is the variable index in
// the context object on the heap, starting at 0. scope() is the
// corresponding scope.
CONTEXT,
// A named slot in a heap context. name() is the variable name in the
// context object on the heap, with lookup starting at the current
// context. index() is invalid.
LOOKUP
};
Variable(Scope* scope, Variable(Scope* scope,
Handle<String> name, Handle<String> name,
Mode mode, Mode mode,
...@@ -83,10 +110,6 @@ class Variable: public ZoneObject { ...@@ -83,10 +110,6 @@ class Variable: public ZoneObject {
// Printing support // Printing support
static const char* Mode2String(Mode mode); static const char* Mode2String(Mode mode);
// Type testing & conversion. Global variables are not slots.
Property* AsProperty() const;
Slot* AsSlot() const;
bool IsValidLeftHandSide() { return is_valid_LHS_; } bool IsValidLeftHandSide() { return is_valid_LHS_; }
// The source code for an eval() call may refer to a variable that is // The source code for an eval() call may refer to a variable that is
...@@ -111,10 +134,12 @@ class Variable: public ZoneObject { ...@@ -111,10 +134,12 @@ class Variable: public ZoneObject {
return !is_this() && name().is_identical_to(n); return !is_this() && name().is_identical_to(n);
} }
bool IsStackAllocated() const; bool IsUnallocated() const { return location_ == UNALLOCATED; }
bool IsParameter() const; // Includes 'this'. bool IsParameter() const { return location_ == PARAMETER; }
bool IsStackLocal() const; bool IsStackLocal() const { return location_ == LOCAL; }
bool IsContextSlot() const; bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); }
bool IsContextSlot() const { return location_ == CONTEXT; }
bool IsLookupSlot() const { return location_ == LOOKUP; }
bool is_dynamic() const { bool is_dynamic() const {
return (mode_ == DYNAMIC || return (mode_ == DYNAMIC ||
...@@ -141,20 +166,24 @@ class Variable: public ZoneObject { ...@@ -141,20 +166,24 @@ class Variable: public ZoneObject {
local_if_not_shadowed_ = local; local_if_not_shadowed_ = local;
} }
Slot* rewrite() const { return rewrite_; } Location location() const { return location_; }
void set_rewrite(Slot* slot) { rewrite_ = slot; } int index() const { return index_; }
void AllocateTo(Location location, int index) {
location_ = location;
index_ = index;
}
private: private:
Scope* scope_; Scope* scope_;
Handle<String> name_; Handle<String> name_;
Mode mode_; Mode mode_;
Kind kind_; Kind kind_;
Location location_;
int index_;
Variable* local_if_not_shadowed_; Variable* local_if_not_shadowed_;
// Code generation.
Slot* rewrite_;
// Valid as a LHS? (const and this are not valid LHS, for example) // Valid as a LHS? (const and this are not valid LHS, for example)
bool is_valid_LHS_; bool is_valid_LHS_;
......
This diff is collapsed.
...@@ -207,14 +207,14 @@ bool LCodeGen::GeneratePrologue() { ...@@ -207,14 +207,14 @@ bool LCodeGen::GeneratePrologue() {
// Copy any necessary parameters into the context. // Copy any necessary parameters into the context.
int num_parameters = scope()->num_parameters(); int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) { for (int i = 0; i < num_parameters; i++) {
Slot* slot = scope()->parameter(i)->AsSlot(); Variable* var = scope()->parameter(i);
if (slot != NULL && slot->type() == Slot::CONTEXT) { if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset + int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize; (num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack. // Load parameter from stack.
__ movq(rax, Operand(rbp, parameter_offset)); __ movq(rax, Operand(rbp, parameter_offset));
// Store it in the context. // Store it in the context.
int context_offset = Context::SlotOffset(slot->index()); int context_offset = Context::SlotOffset(var->index());
__ movq(Operand(rsi, context_offset), rax); __ movq(Operand(rsi, context_offset), rax);
// Update the write barrier. This clobbers all involved // Update the write barrier. This clobbers all involved
// registers, so we have use a third register to avoid // registers, so we have use a third register to avoid
......
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -66,6 +66,7 @@ assertEquals(2, ((delete 0) || 2) + 1); ...@@ -66,6 +66,7 @@ assertEquals(2, ((delete 0) || 2) + 1);
assertEquals(3, (function (x) { return ((delete x) || 2) + 1; })(0)); assertEquals(3, (function (x) { return ((delete x) || 2) + 1; })(0));
// 'this' at toplevel is different from all other global variables---not // 'this' is not a Reference so delete returns true (see section 11.4.1,
// deletable. // step 2 of ES 5.1).
assertEquals(true, delete this); assertEquals(true, delete this);
assertEquals(true, (function () { return delete this; })());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment