summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-07-12 16:37:06 +0100
committerBen Murdoch <benm@google.com>2011-07-13 11:00:43 +0100
commit7d3e7fc4b65010eabe860313ee0c64f50843f6e3 (patch)
tree1cf559005d8e87c1c1d2c4d1af29fecc9fd0b08c /src
parentd85c14422ed4297762a73b74af12e7957a63cb74 (diff)
downloadandroid_external_v8-7d3e7fc4b65010eabe860313ee0c64f50843f6e3.tar.gz
android_external_v8-7d3e7fc4b65010eabe860313ee0c64f50843f6e3.tar.bz2
android_external_v8-7d3e7fc4b65010eabe860313ee0c64f50843f6e3.zip
Merge V8 at branches/3.2 r8606: Initial merge by Git.
Change-Id: I9906d4a1145c7fab2ad78e7a9c375205c56d1287
Diffstat (limited to 'src')
-rw-r--r--src/accessors.cc23
-rw-r--r--src/arm/assembler-arm.h4
-rw-r--r--src/arm/code-stubs-arm.cc21
-rw-r--r--src/arm/frames-arm.h3
-rw-r--r--src/arm/lithium-arm.cc6
-rw-r--r--src/arm/lithium-arm.h1
-rw-r--r--src/arm/lithium-codegen-arm.cc32
-rw-r--r--src/arm/lithium-codegen-arm.h1
-rwxr-xr-xsrc/compiler.cc8
-rw-r--r--src/full-codegen.cc5
-rw-r--r--src/hydrogen-instructions.cc5
-rw-r--r--src/hydrogen-instructions.h14
-rw-r--r--src/hydrogen.cc95
-rw-r--r--src/hydrogen.h3
-rw-r--r--src/ia32/lithium-codegen-ia32.cc31
-rw-r--r--src/ia32/lithium-codegen-ia32.h5
-rw-r--r--src/ia32/lithium-ia32.cc6
-rw-r--r--src/ia32/lithium-ia32.h1
-rw-r--r--src/lithium.h3
-rw-r--r--src/objects.cc12
-rw-r--r--src/platform-solaris.cc5
-rw-r--r--src/version.cc2
-rw-r--r--src/x64/lithium-codegen-x64.cc33
-rw-r--r--src/x64/lithium-codegen-x64.h5
-rw-r--r--src/x64/lithium-x64.cc4
-rw-r--r--src/x64/lithium-x64.h1
26 files changed, 244 insertions, 85 deletions
diff --git a/src/accessors.cc b/src/accessors.cc
index 5f9bf744..7fa69824 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -101,6 +101,15 @@ Object* Accessors::FlattenNumber(Object* value) {
MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
Isolate* isolate = object->GetIsolate();
+
+ // This means one of the object's prototypes is a JSArray and the
+ // object does not have a 'length' property. Calling SetProperty
+ // causes an infinite loop.
+ if (!object->IsJSArray()) {
+ return object->SetLocalPropertyIgnoreAttributes(
+ isolate->heap()->length_symbol(), value, NONE);
+ }
+
value = FlattenNumber(value);
// Need to call methods that may trigger GC.
@@ -116,20 +125,8 @@ MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
Handle<Object> number_v = Execution::ToNumber(value_handle, &has_exception);
if (has_exception) return Failure::Exception();
- // Restore raw pointers,
- object = *object_handle;
- value = *value_handle;
-
if (uint32_v->Number() == number_v->Number()) {
- if (object->IsJSArray()) {
- return JSArray::cast(object)->SetElementsLength(*uint32_v);
- } else {
- // This means one of the object's prototypes is a JSArray and
- // the object does not have a 'length' property.
- // Calling SetProperty causes an infinite loop.
- return object->SetLocalPropertyIgnoreAttributes(
- isolate->heap()->length_symbol(), value, NONE);
- }
+ return Handle<JSArray>::cast(object_handle)->SetElementsLength(*uint32_v);
}
return isolate->Throw(
*isolate->factory()->NewRangeError("invalid_array_length",
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 9050c2c5..3f2daab5 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -302,6 +302,10 @@ const DwVfpRegister d13 = { 13 };
const DwVfpRegister d14 = { 14 };
const DwVfpRegister d15 = { 15 };
+// Aliases for double registers.
+const DwVfpRegister kFirstCalleeSavedDoubleReg = d8;
+const DwVfpRegister kLastCalleeSavedDoubleReg = d15;
+
// Coprocessor register
struct CRegister {
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 8c147f92..fad9339f 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -3413,12 +3413,24 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Save callee-saved registers (incl. cp and fp), sp, and lr
__ stm(db_w, sp, kCalleeSaved | lr.bit());
+ if (CpuFeatures::IsSupported(VFP3)) {
+ CpuFeatures::Scope scope(VFP3);
+ // Save callee-saved vfp registers.
+ __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
+ }
+
// Get address of argv, see stm above.
// r0: code entry
// r1: function
// r2: receiver
// r3: argc
- __ ldr(r4, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize)); // argv
+
+ // Setup argv in r4.
+ int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
+ if (CpuFeatures::IsSupported(VFP3)) {
+ offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize;
+ }
+ __ ldr(r4, MemOperand(sp, offset_to_argv));
// Push a frame with special values setup to mark it as an entry frame.
// r0: code entry
@@ -3543,6 +3555,13 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ mov(lr, Operand(pc));
}
#endif
+
+ if (CpuFeatures::IsSupported(VFP3)) {
+ CpuFeatures::Scope scope(VFP3);
+ // Restore callee-saved vfp registers.
+ __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
+ }
+
__ ldm(ia_w, sp, kCalleeSaved | pc.bit());
}
diff --git a/src/arm/frames-arm.h b/src/arm/frames-arm.h
index d6846c85..84e108b3 100644
--- a/src/arm/frames-arm.h
+++ b/src/arm/frames-arm.h
@@ -72,6 +72,9 @@ static const RegList kCalleeSaved =
static const int kNumCalleeSaved = 7 + kR9Available;
+// Double registers d8 to d15 are callee-saved.
+static const int kNumDoubleCalleeSaved = 8;
+
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 3f1d15bd..efd226ea 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1096,7 +1096,7 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
ASSERT(compare->value()->representation().IsTagged());
LOperand* temp = TempRegister();
- return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), temp);
+ return new LIsObjectAndBranch(UseRegister(compare->value()), temp);
} else if (v->IsCompareJSObjectEq()) {
HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
@@ -2010,6 +2010,10 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
+ if (spill_index > LUnallocated::kMaxFixedIndex) {
+ Abort("Too many spill slots needed for OSR");
+ spill_index = 0;
+ }
return DefineAsSpilled(new LUnknownOSRValue, spill_index);
}
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 6da7c861..e1c65d22 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -1583,6 +1583,7 @@ class LNumberUntagD: public LTemplateInstruction<1, 1, 0> {
}
DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
+ DECLARE_HYDROGEN_ACCESSOR(Change)
};
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 49124497..80055708 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -839,6 +839,8 @@ void LCodeGen::DoModI(LModI* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ b(ne, &done);
DeoptimizeIf(al, instr->environment());
+ } else {
+ __ b(&done);
}
__ bind(&positive_dividend);
__ and_(dividend, dividend, Operand(divisor - 1));
@@ -3560,6 +3562,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
DoubleRegister result_reg,
+ bool deoptimize_on_undefined,
LEnvironment* env) {
Register scratch = scratch0();
SwVfpRegister flt_scratch = s0;
@@ -3575,20 +3578,25 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
__ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(scratch, Operand(ip));
- __ b(eq, &heap_number);
+ if (deoptimize_on_undefined) {
+ DeoptimizeIf(ne, env);
+ } else {
+ Label heap_number;
+ __ b(eq, &heap_number);
- __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
- __ cmp(input_reg, Operand(ip));
- DeoptimizeIf(ne, env);
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+ __ cmp(input_reg, Operand(ip));
+ DeoptimizeIf(ne, env);
- // Convert undefined to NaN.
- __ LoadRoot(ip, Heap::kNanValueRootIndex);
- __ sub(ip, ip, Operand(kHeapObjectTag));
- __ vldr(result_reg, ip, HeapNumber::kValueOffset);
- __ jmp(&done);
+ // Convert undefined to NaN.
+ __ LoadRoot(ip, Heap::kNanValueRootIndex);
+ __ sub(ip, ip, Operand(kHeapObjectTag));
+ __ vldr(result_reg, ip, HeapNumber::kValueOffset);
+ __ jmp(&done);
+ __ bind(&heap_number);
+ }
// Heap number to double register conversion.
- __ bind(&heap_number);
__ sub(ip, input_reg, Operand(kHeapObjectTag));
__ vldr(result_reg, ip, HeapNumber::kValueOffset);
__ jmp(&done);
@@ -3717,7 +3725,9 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
Register input_reg = ToRegister(input);
DoubleRegister result_reg = ToDoubleRegister(result);
- EmitNumberUntagD(input_reg, result_reg, instr->environment());
+ EmitNumberUntagD(input_reg, result_reg,
+ instr->hydrogen()->deoptimize_on_undefined(),
+ instr->environment());
}
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 8a4ea27d..092e7b77 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -262,6 +262,7 @@ class LCodeGen BASE_EMBEDDED {
void EmitCmpI(LOperand* left, LOperand* right);
void EmitNumberUntagD(Register input,
DoubleRegister result,
+ bool deoptimize_on_undefined,
LEnvironment* env);
// Emits optimized code for typeof x == "y". Modifies input register.
diff --git a/src/compiler.cc b/src/compiler.cc
index 86d5de3a..d8c7706c 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -233,10 +233,12 @@ static bool MakeCrankshaftCode(CompilationInfo* info) {
//
// The encoding is as a signed value, with parameters and receiver using
// the negative indices and locals the non-negative ones.
- const int limit = LUnallocated::kMaxFixedIndices / 2;
+ const int parameter_limit = -LUnallocated::kMinFixedIndex;
+ const int locals_limit = LUnallocated::kMaxFixedIndex;
Scope* scope = info->scope();
- if ((scope->num_parameters() + 1) > limit ||
- scope->num_stack_slots() > limit) {
+ if ((scope->num_parameters() + 1) > parameter_limit ||
+ (info->osr_ast_id() != AstNode::kNoNumber &&
+ scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) {
AbortAndDisable(info);
// True indicates the compilation pipeline is still going, not
// necessarily that we optimized the code.
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index d6ba56e8..5f97421c 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -247,7 +247,10 @@ void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
Visit(expr->left());
- Visit(expr->right());
+ if (expr->op() != Token::AND &&
+ expr->op() != Token::OR) {
+ Visit(expr->right());
+ }
}
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 032ca769..2cf60d7b 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1157,6 +1157,10 @@ void HCompare::SetInputRepresentation(Representation r) {
if (r.IsTagged()) {
SetAllSideEffects();
ClearFlag(kUseGVN);
+ } else if (r.IsDouble()) {
+ SetFlag(kDeoptimizeOnUndefined);
+ ClearAllSideEffects();
+ SetFlag(kUseGVN);
} else {
ClearAllSideEffects();
SetFlag(kUseGVN);
@@ -1612,7 +1616,6 @@ void HSimulate::Verify() {
void HBoundsCheck::Verify() {
HInstruction::Verify();
- ASSERT(HasNoUses());
}
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index a623775f..d5f4ea13 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -424,6 +424,7 @@ class HValue: public ZoneObject {
kCanOverflow,
kBailoutOnMinusZero,
kCanBeDivByZero,
+ kDeoptimizeOnUndefined,
kIsArguments,
kTruncatingToInt32,
kLastFlag = kTruncatingToInt32
@@ -938,8 +939,11 @@ class HChange: public HUnaryOperation {
HChange(HValue* value,
Representation from,
Representation to,
- bool is_truncating)
- : HUnaryOperation(value), from_(from) {
+ bool is_truncating,
+ bool deoptimize_on_undefined)
+ : HUnaryOperation(value),
+ from_(from),
+ deoptimize_on_undefined_(deoptimize_on_undefined) {
ASSERT(!from.IsNone() && !to.IsNone());
ASSERT(!from.Equals(to));
set_representation(to);
@@ -955,6 +959,7 @@ class HChange: public HUnaryOperation {
Representation from() const { return from_; }
Representation to() const { return representation(); }
+ bool deoptimize_on_undefined() const { return deoptimize_on_undefined_; }
virtual Representation RequiredInputRepresentation(int index) const {
return from_;
}
@@ -971,11 +976,13 @@ class HChange: public HUnaryOperation {
if (!other->IsChange()) return false;
HChange* change = HChange::cast(other);
return value() == change->value()
- && to().Equals(change->to());
+ && to().Equals(change->to())
+ && deoptimize_on_undefined() == change->deoptimize_on_undefined();
}
private:
Representation from_;
+ bool deoptimize_on_undefined_;
};
@@ -2133,6 +2140,7 @@ class HBoundsCheck: public HBinaryOperation {
public:
HBoundsCheck(HValue* index, HValue* length)
: HBinaryOperation(index, length) {
+ set_representation(Representation::Integer32());
SetFlag(kUseGVN);
}
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 73ea97d0..086b0e7e 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1765,6 +1765,7 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
// change instructions for them.
HInstruction* new_value = NULL;
bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32);
+ bool deoptimize_on_undefined = use->CheckFlag(HValue::kDeoptimizeOnUndefined);
if (value->IsConstant()) {
HConstant* constant = HConstant::cast(value);
// Try to create a new copy of the constant with the new representation.
@@ -1774,8 +1775,8 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
}
if (new_value == NULL) {
- new_value =
- new(zone()) HChange(value, value->representation(), to, is_truncating);
+ new_value = new(zone()) HChange(value, value->representation(), to,
+ is_truncating, deoptimize_on_undefined);
}
new_value->InsertBefore(next);
@@ -1916,6 +1917,41 @@ void HGraph::InsertRepresentationChanges() {
}
+void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
+ if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return;
+ phi->SetFlag(HValue::kDeoptimizeOnUndefined);
+ for (int i = 0; i < phi->OperandCount(); ++i) {
+ HValue* input = phi->OperandAt(i);
+ if (input->IsPhi()) {
+ RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input));
+ }
+ }
+}
+
+
+void HGraph::MarkDeoptimizeOnUndefined() {
+ HPhase phase("MarkDeoptimizeOnUndefined", this);
+ // Compute DeoptimizeOnUndefined flag for phis.
+ // Any phi that can reach a use with DeoptimizeOnUndefined set must
+ // have DeoptimizeOnUndefined set. Currently only HCompare, with
+ // double input representation, has this flag set.
+ // The flag is used by HChange tagged->double, which must deoptimize
+ // if one of its uses has this flag set.
+ for (int i = 0; i < phi_list()->length(); i++) {
+ HPhi* phi = phi_list()->at(i);
+ if (phi->representation().IsDouble()) {
+ for (int j = 0; j < phi->uses()->length(); j++) {
+ HValue* use = phi->uses()->at(j);
+ if (use->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
+ RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
+ break;
+ }
+ }
+ }
+ }
+}
+
+
void HGraph::ComputeMinusZeroChecks() {
BitVector visited(GetMaximumValueID());
for (int i = 0; i < blocks_.length(); ++i) {
@@ -2234,6 +2270,7 @@ HGraph* HGraphBuilder::CreateGraph() {
graph()->InitializeInferredTypes();
graph()->Canonicalize();
+ graph()->MarkDeoptimizeOnUndefined();
graph()->InsertRepresentationChanges();
graph()->ComputeMinusZeroChecks();
@@ -2248,10 +2285,32 @@ HGraph* HGraphBuilder::CreateGraph() {
gvn.Analyze();
}
+ // Replace the results of check instructions with the original value, if the
+ // result is used. This is safe now, since we don't do code motion after this
+ // point. It enables better register allocation since the value produced by
+ // check instructions is really a copy of the original value.
+ graph()->ReplaceCheckedValues();
+
return graph();
}
+void HGraph::ReplaceCheckedValues() {
+ HPhase phase("Replace checked values", this);
+ for (int i = 0; i < blocks()->length(); ++i) {
+ HInstruction* instr = blocks()->at(i)->first();
+ while (instr != NULL) {
+ if (instr->IsBoundsCheck()) {
+ // Replace all uses of the checked value with the original input.
+ ASSERT(instr->uses()->length() > 0);
+ instr->ReplaceValue(HBoundsCheck::cast(instr)->index());
+ }
+ instr = instr->next();
+ }
+ }
+}
+
+
HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
ASSERT(current_block() != NULL);
current_block()->AddInstruction(instr);
@@ -3580,16 +3639,17 @@ HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
HLoadElements* elements = new(zone()) HLoadElements(object);
HInstruction* length = NULL;
+ HInstruction* checked_key = NULL;
if (is_array) {
length = AddInstruction(new(zone()) HJSArrayLength(object));
- AddInstruction(new(zone()) HBoundsCheck(key, length));
+ checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
AddInstruction(elements);
} else {
AddInstruction(elements);
length = AddInstruction(new(zone()) HFixedArrayLength(elements));
- AddInstruction(new(zone()) HBoundsCheck(key, length));
+ checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
}
- return new(zone()) HLoadKeyedFastElement(elements, key);
+ return new(zone()) HLoadKeyedFastElement(elements, checked_key);
}
@@ -3607,13 +3667,14 @@ HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement(
AddInstruction(elements);
HInstruction* length = new(zone()) HExternalArrayLength(elements);
AddInstruction(length);
- AddInstruction(new(zone()) HBoundsCheck(key, length));
+ HInstruction* checked_key =
+ AddInstruction(new(zone()) HBoundsCheck(key, length));
HLoadExternalArrayPointer* external_elements =
new(zone()) HLoadExternalArrayPointer(elements);
AddInstruction(external_elements);
HLoadKeyedSpecializedArrayElement* pixel_array_value =
new(zone()) HLoadKeyedSpecializedArrayElement(
- external_elements, key, expr->external_array_type());
+ external_elements, checked_key, expr->external_array_type());
return pixel_array_value;
}
@@ -3669,8 +3730,9 @@ HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
} else {
length = AddInstruction(new(zone()) HFixedArrayLength(elements));
}
- AddInstruction(new(zone()) HBoundsCheck(key, length));
- return new(zone()) HStoreKeyedFastElement(elements, key, val);
+ HInstruction* checked_key =
+ AddInstruction(new(zone()) HBoundsCheck(key, length));
+ return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
}
@@ -3689,13 +3751,14 @@ HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
AddInstruction(elements);
HInstruction* length = AddInstruction(
new(zone()) HExternalArrayLength(elements));
- AddInstruction(new(zone()) HBoundsCheck(key, length));
+ HInstruction* checked_key =
+ AddInstruction(new(zone()) HBoundsCheck(key, length));
HLoadExternalArrayPointer* external_elements =
new(zone()) HLoadExternalArrayPointer(elements);
AddInstruction(external_elements);
return new(zone()) HStoreKeyedSpecializedArrayElement(
external_elements,
- key,
+ checked_key,
val,
expr->external_array_type());
}
@@ -3746,8 +3809,9 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
HInstruction* length = AddInstruction(
new(zone()) HArgumentsLength(elements));
- AddInstruction(new(zone()) HBoundsCheck(key, length));
- result = new(zone()) HAccessArgumentsAt(elements, length, key);
+ HInstruction* checked_key =
+ AddInstruction(new(zone()) HBoundsCheck(key, length));
+ result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
}
ast_context()->ReturnInstruction(result, expr->id());
return true;
@@ -4778,8 +4842,9 @@ HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string,
string, FIRST_STRING_TYPE, LAST_STRING_TYPE));
HStringLength* length = new(zone()) HStringLength(string);
AddInstruction(length);
- AddInstruction(new(zone()) HBoundsCheck(index, length));
- return new(zone()) HStringCharCodeAt(string, index);
+ HInstruction* checked_index =
+ AddInstruction(new(zone()) HBoundsCheck(index, length));
+ return new(zone()) HStringCharCodeAt(string, checked_index);
}
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 74c119a2..fbd279f6 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -214,6 +214,7 @@ class HGraph: public ZoneObject {
void InitializeInferredTypes();
void InsertTypeConversions();
void InsertRepresentationChanges();
+ void MarkDeoptimizeOnUndefined();
void ComputeMinusZeroChecks();
bool ProcessArgumentsObject();
void EliminateRedundantPhis();
@@ -221,6 +222,7 @@ class HGraph: public ZoneObject {
void Canonicalize();
void OrderBlocks();
void AssignDominators();
+ void ReplaceCheckedValues();
// Returns false if there are phi-uses of the arguments-object
// which are not supported by the optimizing compiler.
@@ -276,6 +278,7 @@ class HGraph: public ZoneObject {
void InsertTypeConversions(HInstruction* instr);
void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
+ void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
void InsertRepresentationChangeForUse(HValue* value,
HValue* use,
Representation to);
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 0f96f78c..73565dc3 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -789,6 +789,8 @@ void LCodeGen::DoModI(LModI* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ j(not_zero, &done);
DeoptimizeIf(no_condition, instr->environment());
+ } else {
+ __ jmp(&done);
}
__ bind(&positive_dividend);
__ and_(dividend, divisor - 1);
@@ -3424,8 +3426,9 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
XMMRegister result_reg,
+ bool deoptimize_on_undefined,
LEnvironment* env) {
- NearLabel load_smi, heap_number, done;
+ NearLabel load_smi, done;
// Smi check.
__ test(input_reg, Immediate(kSmiTagMask));
@@ -3434,18 +3437,22 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Heap number map check.
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map());
- __ j(equal, &heap_number);
-
- __ cmp(input_reg, factory()->undefined_value());
- DeoptimizeIf(not_equal, env);
+ if (deoptimize_on_undefined) {
+ DeoptimizeIf(not_equal, env);
+ } else {
+ NearLabel heap_number;
+ __ j(equal, &heap_number);
+ __ cmp(input_reg, factory()->undefined_value());
+ DeoptimizeIf(not_equal, env);
- // Convert undefined to NaN.
- ExternalReference nan = ExternalReference::address_of_nan();
- __ movdbl(result_reg, Operand::StaticVariable(nan));
- __ jmp(&done);
+ // Convert undefined to NaN.
+ ExternalReference nan = ExternalReference::address_of_nan();
+ __ movdbl(result_reg, Operand::StaticVariable(nan));
+ __ jmp(&done);
+ __ bind(&heap_number);
+ }
// Heap number to XMM conversion.
- __ bind(&heap_number);
__ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ jmp(&done);
@@ -3578,7 +3585,9 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
Register input_reg = ToRegister(input);
XMMRegister result_reg = ToDoubleRegister(result);
- EmitNumberUntagD(input_reg, result_reg, instr->environment());
+ EmitNumberUntagD(input_reg, result_reg,
+ instr->hydrogen()->deoptimize_on_undefined(),
+ instr->environment());
}
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index 6d42cd78..bdccd3c4 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -256,7 +256,10 @@ class LCodeGen BASE_EMBEDDED {
void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
void EmitBranch(int left_block, int right_block, Condition cc);
void EmitCmpI(LOperand* left, LOperand* right);
- void EmitNumberUntagD(Register input, XMMRegister result, LEnvironment* env);
+ void EmitNumberUntagD(Register input,
+ XMMRegister result,
+ bool deoptimize_on_undefined,
+ LEnvironment* env);
// Emits optimized code for typeof x == "y". Modifies input register.
// Returns the condition on which a final split to
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 9ccd1897..4b10562e 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1098,7 +1098,7 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
- return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()),
+ return new LIsObjectAndBranch(UseRegister(compare->value()),
temp1,
temp2);
} else if (v->IsCompareJSObjectEq()) {
@@ -2066,6 +2066,10 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
+ if (spill_index > LUnallocated::kMaxFixedIndex) {
+ Abort("Too many spill slots needed for OSR");
+ spill_index = 0;
+ }
return DefineAsSpilled(new LUnknownOSRValue, spill_index);
}
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 9ace8f86..be5658b1 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -1635,6 +1635,7 @@ class LNumberUntagD: public LTemplateInstruction<1, 1, 0> {
}
DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
+ DECLARE_HYDROGEN_ACCESSOR(Change);
};
diff --git a/src/lithium.h b/src/lithium.h
index d85a87c1..280da472 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -143,7 +143,8 @@ class LUnallocated: public LOperand {
};
static const int kMaxVirtualRegisters = 1 << (kVirtualRegisterWidth + 1);
- static const int kMaxFixedIndices = 128;
+ static const int kMaxFixedIndex = 63;
+ static const int kMinFixedIndex = -64;
bool HasIgnorePolicy() const { return policy() == IGNORE; }
bool HasNoPolicy() const { return policy() == NONE; }
diff --git a/src/objects.cc b/src/objects.cc
index a20548c6..8491d588 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1813,13 +1813,9 @@ void JSObject::LookupCallbackSetterInPrototypes(String* name,
pt = pt->GetPrototype()) {
JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
if (result->IsProperty()) {
- if (result->IsReadOnly()) {
- result->NotFound();
- return;
- }
- if (result->type() == CALLBACKS) {
- return;
- }
+ if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
+ // Found non-callback or read-only callback, stop looking.
+ break;
}
}
result->NotFound();
@@ -3745,6 +3741,8 @@ void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
}
}
if (!map_done) continue;
+ } else {
+ map_or_index_field = NULL;
}
// That was the regular transitions, now for the prototype transitions.
FixedArray* prototype_transitions =
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index 1a19bac3..970c4186 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2009 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
// modification, are permitted provided that the following conditions are
// met:
@@ -105,7 +105,8 @@ uint64_t OS::CpuFeaturesImpliedByPlatform() {
int OS::ActivationFrameAlignment() {
- return STACK_ALIGN;
+ // GCC generates code that requires 16 byte alignment such as movdqa.
+ return Max(STACK_ALIGN, 16);
}
diff --git a/src/version.cc b/src/version.cc
index 71a07db9..822abfe7 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 3
#define MINOR_VERSION 2
#define BUILD_NUMBER 10
-#define PATCH_LEVEL 16
+#define PATCH_LEVEL 28
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 202e7a24..a178d034 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -789,6 +789,8 @@ void LCodeGen::DoModI(LModI* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ j(not_zero, &done);
DeoptimizeIf(no_condition, instr->environment());
+ } else {
+ __ jmp(&done);
}
__ bind(&positive_dividend);
__ andl(dividend, Immediate(divisor - 1));
@@ -2688,7 +2690,9 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
Register input_reg = ToRegister(instr->InputAt(0));
// Smi check.
__ JumpIfNotSmi(input_reg, deferred->entry());
+ __ SmiToInteger32(input_reg, input_reg);
EmitIntegerMathAbs(instr);
+ __ Integer32ToSmi(input_reg, input_reg);
__ bind(deferred->exit());
}
}
@@ -3362,8 +3366,9 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
XMMRegister result_reg,
+ bool deoptimize_on_undefined,
LEnvironment* env) {
- NearLabel load_smi, heap_number, done;
+ NearLabel load_smi, done;
// Smi check.
__ JumpIfSmi(input_reg, &load_smi);
@@ -3371,18 +3376,22 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Heap number map check.
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
- __ j(equal, &heap_number);
-
- __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
- DeoptimizeIf(not_equal, env);
+ if (deoptimize_on_undefined) {
+ DeoptimizeIf(not_equal, env);
+ } else {
+ NearLabel heap_number;
+ __ j(equal, &heap_number);
+ __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
+ DeoptimizeIf(not_equal, env);
- // Convert undefined to NaN. Compute NaN as 0/0.
- __ xorpd(result_reg, result_reg);
- __ divsd(result_reg, result_reg);
- __ jmp(&done);
+ // Convert undefined to NaN. Compute NaN as 0/0.
+ __ xorpd(result_reg, result_reg);
+ __ divsd(result_reg, result_reg);
+ __ jmp(&done);
+ __ bind(&heap_number);
+ }
// Heap number to XMM conversion.
- __ bind(&heap_number);
__ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ jmp(&done);
@@ -3473,7 +3482,9 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
Register input_reg = ToRegister(input);
XMMRegister result_reg = ToDoubleRegister(result);
- EmitNumberUntagD(input_reg, result_reg, instr->environment());
+ EmitNumberUntagD(input_reg, result_reg,
+ instr->hydrogen()->deoptimize_on_undefined(),
+ instr->environment());
}
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 34277f6e..d95ab21d 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -244,7 +244,10 @@ class LCodeGen BASE_EMBEDDED {
void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
void EmitBranch(int left_block, int right_block, Condition cc);
void EmitCmpI(LOperand* left, LOperand* right);
- void EmitNumberUntagD(Register input, XMMRegister result, LEnvironment* env);
+ void EmitNumberUntagD(Register input,
+ XMMRegister result,
+ bool deoptimize_on_undefined,
+ LEnvironment* env);
// Emits optimized code for typeof x == "y". Modifies input register.
// Returns the condition on which a final split to
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 07ca3a51..4601cd9f 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -2004,6 +2004,10 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
+ if (spill_index > LUnallocated::kMaxFixedIndex) {
+ Abort("Too many spill slots needed for OSR");
+ spill_index = 0;
+ }
return DefineAsSpilled(new LUnknownOSRValue, spill_index);
}
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 15bb8941..8e122821 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -1559,6 +1559,7 @@ class LNumberUntagD: public LTemplateInstruction<1, 1, 0> {
}
DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
+ DECLARE_HYDROGEN_ACCESSOR(Change);
};