Version 2.4.0.
Fix bug in Object.freeze and Object.seal when Array.prototype or Object.prototype is changed (issue 842).
Update Array.splice to follow Safari and Firefox when called with zero arguments.
Fix a missing live register when breaking at keyed loads on ARM.
Performance improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@5388 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 61fbd76..912fefc 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -29,7 +29,7 @@
#if defined(V8_TARGET_ARCH_ARM)
-#include "code-stubs-arm.h"
+#include "code-stubs.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "debug.h"
@@ -246,6 +246,13 @@
}
+FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
+ Token::Value op, Expression* left, Expression* right) {
+ ASSERT(ShouldInlineSmiCase(op));
+ return kNoConstants;
+}
+
+
void FullCodeGenerator::Apply(Expression::Context context, Register reg) {
switch (context) {
case Expression::kUninitialized:
@@ -1144,10 +1151,11 @@
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
LhsKind assign_type = VARIABLE;
- Property* prop = expr->target()->AsProperty();
- if (prop != NULL) {
- assign_type =
- (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
+ Property* property = expr->target()->AsProperty();
+ if (property != NULL) {
+ assign_type = (property->key()->IsPropertyName())
+ ? NAMED_PROPERTY
+ : KEYED_PROPERTY;
}
// Evaluate LHS expression.
@@ -1158,61 +1166,70 @@
case NAMED_PROPERTY:
if (expr->is_compound()) {
// We need the receiver both on the stack and in the accumulator.
- VisitForValue(prop->obj(), kAccumulator);
+ VisitForValue(property->obj(), kAccumulator);
__ push(result_register());
} else {
- VisitForValue(prop->obj(), kStack);
+ VisitForValue(property->obj(), kStack);
}
break;
case KEYED_PROPERTY:
- // We need the key and receiver on both the stack and in r0 and r1.
if (expr->is_compound()) {
- VisitForValue(prop->obj(), kStack);
- VisitForValue(prop->key(), kAccumulator);
+ VisitForValue(property->obj(), kStack);
+ VisitForValue(property->key(), kAccumulator);
__ ldr(r1, MemOperand(sp, 0));
__ push(r0);
} else {
- VisitForValue(prop->obj(), kStack);
- VisitForValue(prop->key(), kStack);
+ VisitForValue(property->obj(), kStack);
+ VisitForValue(property->key(), kStack);
}
break;
}
- // If we have a compound assignment: Get value of LHS expression and
- // store in on top of the stack.
if (expr->is_compound()) {
Location saved_location = location_;
- location_ = kStack;
+ location_ = kAccumulator;
switch (assign_type) {
case VARIABLE:
EmitVariableLoad(expr->target()->AsVariableProxy()->var(),
Expression::kValue);
break;
case NAMED_PROPERTY:
- EmitNamedPropertyLoad(prop);
- __ push(result_register());
+ EmitNamedPropertyLoad(property);
break;
case KEYED_PROPERTY:
- EmitKeyedPropertyLoad(prop);
- __ push(result_register());
+ EmitKeyedPropertyLoad(property);
break;
}
- location_ = saved_location;
- }
- // Evaluate RHS expression.
- Expression* rhs = expr->value();
- VisitForValue(rhs, kAccumulator);
+ Token::Value op = expr->binary_op();
+ ConstantOperand constant = ShouldInlineSmiCase(op)
+ ? GetConstantOperand(op, expr->target(), expr->value())
+ : kNoConstants;
+ ASSERT(constant == kRightConstant || constant == kNoConstants);
+ if (constant == kNoConstants) {
+ __ push(r0); // Left operand goes on the stack.
+ VisitForValue(expr->value(), kAccumulator);
+ }
- // If we have a compound assignment: Apply operator.
- if (expr->is_compound()) {
- Location saved_location = location_;
- location_ = kAccumulator;
OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
? OVERWRITE_RIGHT
: NO_OVERWRITE;
- EmitBinaryOp(expr->binary_op(), Expression::kValue, mode);
+ SetSourcePosition(expr->position() + 1);
+ if (ShouldInlineSmiCase(op)) {
+ EmitInlineSmiBinaryOp(expr,
+ op,
+ Expression::kValue,
+ mode,
+ expr->target(),
+ expr->value(),
+ constant);
+ } else {
+ EmitBinaryOp(op, Expression::kValue, mode);
+ }
location_ = saved_location;
+
+ } else {
+ VisitForValue(expr->value(), kAccumulator);
}
// Record source position before possible IC call.
@@ -1253,6 +1270,18 @@
}
+void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
+ Token::Value op,
+ Expression::Context context,
+ OverwriteMode mode,
+ Expression* left,
+ Expression* right,
+ ConstantOperand constant) {
+ ASSERT(constant == kNoConstants); // Only handled case.
+ EmitBinaryOp(op, context, mode);
+}
+
+
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
Expression::Context context,
OverwriteMode mode) {
@@ -2510,6 +2539,35 @@
}
+void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
+ VisitForValue(args->at(0), kAccumulator);
+
+ Label materialize_true, materialize_false;
+ Label* if_true = NULL;
+ Label* if_false = NULL;
+ Label* fall_through = NULL;
+ PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
+
+ __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
+ __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
+
+ __ b(eq, if_true);
+ __ b(if_false);
+
+ Apply(context_, if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
+ ASSERT(args->length() == 1);
+ VisitForValue(args->at(0), kAccumulator);
+ __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
+ __ IndexFromHash(r0, r0);
+ Apply(context_, r0);
+}
+
+
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
Handle<String> name = expr->name();
if (name->length() > 0 && name->Get(0) == '_') {