diff options
author | Ben Murdoch <benm@google.com> | 2011-07-12 16:37:06 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-07-13 11:00:43 +0100 |
commit | 7d3e7fc4b65010eabe860313ee0c64f50843f6e3 (patch) | |
tree | 1cf559005d8e87c1c1d2c4d1af29fecc9fd0b08c /src | |
parent | d85c14422ed4297762a73b74af12e7957a63cb74 (diff) | |
download | android_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.cc | 23 | ||||
-rw-r--r-- | src/arm/assembler-arm.h | 4 | ||||
-rw-r--r-- | src/arm/code-stubs-arm.cc | 21 | ||||
-rw-r--r-- | src/arm/frames-arm.h | 3 | ||||
-rw-r--r-- | src/arm/lithium-arm.cc | 6 | ||||
-rw-r--r-- | src/arm/lithium-arm.h | 1 | ||||
-rw-r--r-- | src/arm/lithium-codegen-arm.cc | 32 | ||||
-rw-r--r-- | src/arm/lithium-codegen-arm.h | 1 | ||||
-rwxr-xr-x | src/compiler.cc | 8 | ||||
-rw-r--r-- | src/full-codegen.cc | 5 | ||||
-rw-r--r-- | src/hydrogen-instructions.cc | 5 | ||||
-rw-r--r-- | src/hydrogen-instructions.h | 14 | ||||
-rw-r--r-- | src/hydrogen.cc | 95 | ||||
-rw-r--r-- | src/hydrogen.h | 3 | ||||
-rw-r--r-- | src/ia32/lithium-codegen-ia32.cc | 31 | ||||
-rw-r--r-- | src/ia32/lithium-codegen-ia32.h | 5 | ||||
-rw-r--r-- | src/ia32/lithium-ia32.cc | 6 | ||||
-rw-r--r-- | src/ia32/lithium-ia32.h | 1 | ||||
-rw-r--r-- | src/lithium.h | 3 | ||||
-rw-r--r-- | src/objects.cc | 12 | ||||
-rw-r--r-- | src/platform-solaris.cc | 5 | ||||
-rw-r--r-- | src/version.cc | 2 | ||||
-rw-r--r-- | src/x64/lithium-codegen-x64.cc | 33 | ||||
-rw-r--r-- | src/x64/lithium-codegen-x64.h | 5 | ||||
-rw-r--r-- | src/x64/lithium-x64.cc | 4 | ||||
-rw-r--r-- | src/x64/lithium-x64.h | 1 |
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); }; |