Remove the typeof state threaded through the code generator. It was

used to signal that an expression was the immediate subexpression of
typeof, or (?) in the arm of a conditional expression itself in the
typeof state.

It was inconsistently consulted.  It was not used for property loads,
but only for slot loads.  This means that we matched the Webkit JSC
(not Spidermonkey) behavior for:

typeof(true ? x : y)  // throws ReferenceError

and we matched the SpiderMonkey behavior (not JSC) for:

with ({}) { typeof(true ? x : y) }  // ==> "undefined"

Now we are expected to match the JSC behavior in all cases.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3212 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 54ec6c03
......@@ -35,18 +35,15 @@ namespace internal {
#define __ ACCESS_MASM(masm_)
void CodeGenerator::LoadConditionAndSpill(Expression* expression,
TypeofState typeof_state,
JumpTarget* true_target,
JumpTarget* false_target,
bool force_control) {
LoadCondition(expression, typeof_state, true_target, false_target,
force_control);
LoadCondition(expression, true_target, false_target, force_control);
}
void CodeGenerator::LoadAndSpill(Expression* expression,
TypeofState typeof_state) {
Load(expression, typeof_state);
void CodeGenerator::LoadAndSpill(Expression* expression) {
Load(expression);
}
......@@ -60,8 +57,8 @@ void CodeGenerator::VisitStatementsAndSpill(ZoneList<Statement*>* statements) {
}
void Reference::GetValueAndSpill(TypeofState typeof_state) {
GetValue(typeof_state);
void Reference::GetValueAndSpill() {
GetValue();
}
......
This diff is collapsed.
......@@ -77,12 +77,12 @@ class Reference BASE_EMBEDDED {
// Generate code to push the value of the reference on top of the
// expression stack. The reference is expected to be already on top of
// the expression stack, and it is left in place with its value above it.
void GetValue(TypeofState typeof_state);
void GetValue();
// Generate code to push the value of a reference on top of the expression
// stack and then spill the stack frame. This function is used temporarily
// while the code generator is being transformed.
inline void GetValueAndSpill(TypeofState typeof_state);
inline void GetValueAndSpill();
// Generate code to store the value on top of the expression stack in the
// reference. The reference is expected to be immediately below the value
......@@ -112,10 +112,8 @@ class CodeGenState BASE_EMBEDDED {
explicit CodeGenState(CodeGenerator* owner);
// Create a code generator state based on a code generator's current
// state. The new state has its own typeof state and pair of branch
// labels.
// state. The new state has its own pair of branch labels.
CodeGenState(CodeGenerator* owner,
TypeofState typeof_state,
JumpTarget* true_target,
JumpTarget* false_target);
......@@ -123,13 +121,11 @@ class CodeGenState BASE_EMBEDDED {
// previous state.
~CodeGenState();
TypeofState typeof_state() const { return typeof_state_; }
JumpTarget* true_target() const { return true_target_; }
JumpTarget* false_target() const { return false_target_; }
private:
CodeGenerator* owner_;
TypeofState typeof_state_;
JumpTarget* true_target_;
JumpTarget* false_target_;
CodeGenState* previous_;
......@@ -210,7 +206,6 @@ class CodeGenerator: public AstVisitor {
// State
bool has_cc() const { return cc_reg_ != al; }
TypeofState typeof_state() const { return state_->typeof_state(); }
JumpTarget* true_target() const { return state_->true_target(); }
JumpTarget* false_target() const { return state_->false_target(); }
......@@ -259,25 +254,22 @@ class CodeGenerator: public AstVisitor {
}
void LoadCondition(Expression* x,
TypeofState typeof_state,
JumpTarget* true_target,
JumpTarget* false_target,
bool force_cc);
void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
void Load(Expression* expr);
void LoadGlobal();
void LoadGlobalReceiver(Register scratch);
// Generate code to push the value of an expression on top of the frame
// and then spill the frame fully to memory. This function is used
// temporarily while the code generator is being transformed.
inline void LoadAndSpill(Expression* expression,
TypeofState typeof_state = NOT_INSIDE_TYPEOF);
inline void LoadAndSpill(Expression* expression);
// Call LoadCondition and then spill the virtual frame unless control flow
// cannot reach the end of the expression (ie, by emitting only
// unconditional jumps to the control targets).
inline void LoadConditionAndSpill(Expression* expression,
TypeofState typeof_state,
JumpTarget* true_target,
JumpTarget* false_target,
bool force_control);
......
This diff is collapsed.
......@@ -77,12 +77,12 @@ class Reference BASE_EMBEDDED {
// Generate code to push the value of the reference on top of the
// expression stack. The reference is expected to be already on top of
// the expression stack, and it is left in place with its value above it.
void GetValue(TypeofState typeof_state);
void GetValue();
// Like GetValue except that the slot is expected to be written to before
// being read from again. Thae value of the reference may be invalidated,
// causing subsequent attempts to read it to fail.
void TakeValue(TypeofState typeof_state);
void TakeValue();
// Generate code to store the value on top of the expression stack in the
// reference. The reference is expected to be immediately below the value
......@@ -241,28 +241,20 @@ class CodeGenState BASE_EMBEDDED {
explicit CodeGenState(CodeGenerator* owner);
// Create a code generator state based on a code generator's current
// state. The new state may or may not be inside a typeof, and has its
// own control destination.
CodeGenState(CodeGenerator* owner,
TypeofState typeof_state,
ControlDestination* destination);
// state. The new state has its own control destination.
CodeGenState(CodeGenerator* owner, ControlDestination* destination);
// Destroy a code generator state and restore the owning code generator's
// previous state.
~CodeGenState();
// Accessors for the state.
TypeofState typeof_state() const { return typeof_state_; }
ControlDestination* destination() const { return destination_; }
private:
// The owning code generator.
CodeGenerator* owner_;
// A flag indicating whether we are compiling the immediate subexpression
// of a typeof expression.
TypeofState typeof_state_;
// A control destination in case the expression has a control-flow
// effect.
ControlDestination* destination_;
......@@ -352,7 +344,6 @@ class CodeGenerator: public AstVisitor {
void ProcessDeferred();
// State
TypeofState typeof_state() const { return state_->typeof_state(); }
ControlDestination* destination() const { return state_->destination(); }
// Track loop nesting level.
......@@ -412,18 +403,16 @@ class CodeGenerator: public AstVisitor {
}
void LoadCondition(Expression* x,
TypeofState typeof_state,
ControlDestination* destination,
bool force_control);
void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
void Load(Expression* expr);
void LoadGlobal();
void LoadGlobalReceiver();
// Generate code to push the value of an expression on top of the frame
// and then spill the frame fully to memory. This function is used
// temporarily while the code generator is being transformed.
void LoadAndSpill(Expression* expression,
TypeofState typeof_state = NOT_INSIDE_TYPEOF);
void LoadAndSpill(Expression* expression);
// Read a value from a slot and leave it on top of the expression stack.
void LoadFromSlot(Slot* slot, TypeofState typeof_state);
......
This diff is collapsed.
......@@ -77,12 +77,12 @@ class Reference BASE_EMBEDDED {
// Generate code to push the value of the reference on top of the
// expression stack. The reference is expected to be already on top of
// the expression stack, and it is left in place with its value above it.
void GetValue(TypeofState typeof_state);
void GetValue();
// Like GetValue except that the slot is expected to be written to before
// being read from again. Thae value of the reference may be invalidated,
// causing subsequent attempts to read it to fail.
void TakeValue(TypeofState typeof_state);
void TakeValue();
// Generate code to store the value on top of the expression stack in the
// reference. The reference is expected to be immediately below the value
......@@ -241,28 +241,20 @@ class CodeGenState BASE_EMBEDDED {
explicit CodeGenState(CodeGenerator* owner);
// Create a code generator state based on a code generator's current
// state. The new state may or may not be inside a typeof, and has its
// own control destination.
CodeGenState(CodeGenerator* owner,
TypeofState typeof_state,
ControlDestination* destination);
// state. The new state has its own control destination.
CodeGenState(CodeGenerator* owner, ControlDestination* destination);
// Destroy a code generator state and restore the owning code generator's
// previous state.
~CodeGenState();
// Accessors for the state.
TypeofState typeof_state() const { return typeof_state_; }
ControlDestination* destination() const { return destination_; }
private:
// The owning code generator.
CodeGenerator* owner_;
// A flag indicating whether we are compiling the immediate subexpression
// of a typeof expression.
TypeofState typeof_state_;
// A control destination in case the expression has a control-flow
// effect.
ControlDestination* destination_;
......@@ -353,7 +345,6 @@ class CodeGenerator: public AstVisitor {
bool is_eval() { return is_eval_; }
// State
TypeofState typeof_state() const { return state_->typeof_state(); }
ControlDestination* destination() const { return state_->destination(); }
// Track loop nesting level.
......@@ -414,18 +405,16 @@ class CodeGenerator: public AstVisitor {
}
void LoadCondition(Expression* x,
TypeofState typeof_state,
ControlDestination* destination,
bool force_control);
void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
void Load(Expression* expr);
void LoadGlobal();
void LoadGlobalReceiver();
// Generate code to push the value of an expression on top of the frame
// and then spill the frame fully to memory. This function is used
// temporarily while the code generator is being transformed.
void LoadAndSpill(Expression* expression,
TypeofState typeof_state = NOT_INSIDE_TYPEOF);
void LoadAndSpill(Expression* expression);
// Read a value from a slot and leave it on top of the expression stack.
void LoadFromSlot(Slot* slot, TypeofState typeof_state);
......
......@@ -25,8 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Typeof expression must resolve to undefined when it used on a
// Typeof expression must resolve to 'undefined' when it used on a
// non-existing property. It is *not* allowed to throw a
// ReferenceError.
assertEquals('undefined', typeof xxx);
assertEquals('undefined', eval('typeof xxx'));
assertThrows('typeof(true ? xxx : yyy)', ReferenceError);
assertThrows('with ({}) { typeof(true ? xxx : yyy) }', ReferenceError);
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