Added general pre- and postfix count operations to top-level compiler.

Until now we only supported postfix operations on global variables.
This change add generic count operations to the top-level compiler.

I tried to re-use code from the code generator used for assignment expressions
where possible.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3530 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 88ba93d9
This diff is collapsed.
......@@ -649,12 +649,6 @@ void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
void CodeGenSelector::VisitDeclaration(Declaration* decl) {
Property* prop = decl->proxy()->AsProperty();
if (prop != NULL) {
// Property rewrites are shared, ensure we are not changing its
// expression context state.
ASSERT(prop->obj()->context() == Expression::kUninitialized ||
prop->obj()->context() == Expression::kValue);
ASSERT(prop->key()->context() == Expression::kUninitialized ||
prop->key()->context() == Expression::kValue);
ProcessExpression(prop->obj(), Expression::kValue);
ProcessExpression(prop->key(), Expression::kValue);
}
......@@ -903,8 +897,6 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
}
}
} else if (prop != NULL) {
ASSERT(prop->obj()->context() == Expression::kUninitialized ||
prop->obj()->context() == Expression::kValue);
ProcessExpression(prop->obj(), Expression::kValue);
CHECK_BAILOUT;
// We will only visit the key during code generation for keyed property
......@@ -915,8 +907,6 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
if (lit == NULL ||
!lit->handle()->IsSymbol() ||
String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
ASSERT(prop->key()->context() == Expression::kUninitialized ||
prop->key()->context() == Expression::kValue);
ProcessExpression(prop->key(), Expression::kValue);
CHECK_BAILOUT;
}
......@@ -1022,11 +1012,36 @@ void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
// We support postfix count operations on global variables.
if (expr->is_prefix()) BAILOUT("Prefix CountOperation");
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
if (var == NULL || !var->is_global()) BAILOUT("non-global postincrement");
ProcessExpression(expr->expression(), Expression::kValue);
Property* prop = expr->expression()->AsProperty();
ASSERT(var == NULL || prop == NULL);
if (var != NULL) {
// All global variables are supported.
if (!var->is_global()) {
ASSERT(var->slot() != NULL);
Slot::Type type = var->slot()->type();
if (type == Slot::LOOKUP) {
BAILOUT("CountOperation with lookup slot");
}
}
} else if (prop != NULL) {
ProcessExpression(prop->obj(), Expression::kValue);
CHECK_BAILOUT;
// We will only visit the key during code generation for keyed property
// stores. Leave its expression context uninitialized for named
// property stores.
Literal* lit = prop->key()->AsLiteral();
uint32_t ignored;
if (lit == NULL ||
!lit->handle()->IsSymbol() ||
String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
ProcessExpression(prop->key(), Expression::kValue);
CHECK_BAILOUT;
}
} else {
// This is a throw reference error.
BAILOUT("CountOperation non-variable/non-property expression");
}
}
......
......@@ -676,7 +676,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
EmitNamedPropertyLoad(prop, Expression::kValue);
break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(Expression::kValue);
EmitKeyedPropertyLoad(prop, Expression::kValue);
break;
}
}
......@@ -694,7 +694,8 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// Store the value.
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr);
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->context());
break;
case NAMED_PROPERTY:
EmitNamedPropertyAssignment(expr);
......
......@@ -213,6 +213,7 @@ class FastCodeGenerator: public AstVisitor {
int SlotOffset(Slot* slot);
void Move(Expression::Context destination, Register source);
void MoveTOS(Expression::Context destination);
void Move(Expression::Context destination, Slot* source, Register scratch);
void Move(Expression::Context destination, Literal* source);
void Move(Slot* dst, Register source, Register scratch1, Register scratch2);
......@@ -247,13 +248,13 @@ class FastCodeGenerator: public AstVisitor {
// Platform-specific support for compiling assignments.
// Load a value from a named property and push the result on the stack.
// Load a value from a named property.
// The receiver is left on the stack by the IC.
void EmitNamedPropertyLoad(Property* expr, Expression::Context context);
// Load a value from a named property and push the result on the stack.
// Load a value from a keyed property.
// The receiver and the key is left on the stack by the IC.
void EmitKeyedPropertyLoad(Expression::Context context);
void EmitKeyedPropertyLoad(Property* expr, Expression::Context context);
// Apply the compound assignment operator. Expects both operands on top
// of the stack.
......@@ -261,7 +262,7 @@ class FastCodeGenerator: public AstVisitor {
// Complete a variable assignment. The right-hand-side value is expected
// on top of the stack.
void EmitVariableAssignment(Assignment* expr);
void EmitVariableAssignment(Variable* var, Expression::Context context);
// Complete a named property assignment. The receiver and right-hand-side
// value are expected on top of the stack.
......
This diff is collapsed.
This diff is collapsed.
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Test pre- and postfix count operations.
// Test value context.
var a = 42;
var b = {x:42};
var c = "x";
assertEquals(43, ++a);
assertEquals(43, a);
assertEquals(43, a++);
assertEquals(44, a);
assertEquals(43, ++b.x);
assertEquals(43, b.x);
assertEquals(43, b.x++);
assertEquals(44, b.x);
assertEquals(45, ++b[c]);
assertEquals(45, b[c]);
assertEquals(45, b[c]++);
assertEquals(46, b[c]);
// Test effect context.
a = 42;
b = {x:42};
c = "x";
assertEquals(1, eval("++a; 1"));
assertEquals(43, a);
assertEquals(1, eval("a++; 1"));
assertEquals(44, a);
assertEquals(1, eval("++b.x; 1"));
assertEquals(43, b.x);
assertEquals(1, eval("b.x++; 1"));
assertEquals(44, b.x);
assertEquals(1, eval("++b[c]; 1"));
assertEquals(45, b[c]);
assertEquals(1, eval("b[c]++; 1"));
assertEquals(46, b[c]);
// Test test context.
a = 42;
b = {x:42};
c = "x";
assertEquals(1, (++a) ? 1 : 0);
assertEquals(43, a);
assertEquals(1, (a++) ? 1 : 0);
assertEquals(44, a);
assertEquals(1, (++b.x) ? 1 : 0);
assertEquals(43, b.x);
assertEquals(1, (b.x++) ? 1 : 0);
assertEquals(44, b.x);
assertEquals(1, (++b[c]) ? 1 : 0);
assertEquals(45, b[c]);
assertEquals(1, (b[c]++) ? 1 : 0);
assertEquals(46, b[c]);
// Test value/test and test/value contexts.
a = 42;
b = {x:42};
c = "x";
assertEquals(43, ++a || 1);
assertEquals(43, a);
assertEquals(43, a++ || 1);
assertEquals(44, a);
assertEquals(43, ++b.x || 1);
assertEquals(43, b.x);
assertEquals(43, (b.x++) || 1);
assertEquals(44, b.x);
assertEquals(45, ++b[c] || 1);
assertEquals(45, b[c]);
assertEquals(45, b[c]++ || 1);
assertEquals(46, b[c]);
a = 42;
b = {x:42};
c = "x";
assertEquals(1, ++a && 1);
assertEquals(43, a);
assertEquals(1, a++ && 1);
assertEquals(44, a);
assertEquals(1, ++b.x && 1);
assertEquals(43, b.x);
assertEquals(1, (b.x++) && 1);
assertEquals(44, b.x);
assertEquals(1, ++b[c] && 1);
assertEquals(45, b[c]);
assertEquals(1, b[c]++ && 1);
assertEquals(46, b[c]);
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