From b7c05e1b75e5c64d53b7b0877791ce001020f671 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Wed, 28 Dec 2011 14:13:50 -0800 Subject: [PATCH] Upgrade V8 to 3.8.3 --- deps/v8/ChangeLog | 8 +++ deps/v8/src/arm/lithium-arm.cc | 3 +- deps/v8/src/arm/lithium-codegen-arm.cc | 19 +++--- deps/v8/src/arm/lithium-codegen-arm.h | 3 + deps/v8/src/arm/lithium-gap-resolver-arm.cc | 17 +++++- deps/v8/src/arm/macro-assembler-arm.h | 8 +++ deps/v8/src/debug.cc | 2 +- deps/v8/src/flag-definitions.h | 4 +- deps/v8/src/heap.cc | 2 + deps/v8/src/hydrogen-instructions.h | 4 -- deps/v8/src/hydrogen.cc | 26 +++++--- deps/v8/src/ia32/lithium-codegen-ia32.cc | 31 +++------- deps/v8/src/ia32/lithium-codegen-ia32.h | 10 ++- deps/v8/src/ia32/lithium-gap-resolver-ia32.cc | 18 ++++-- deps/v8/src/ia32/lithium-ia32.cc | 3 +- deps/v8/src/ia32/macro-assembler-ia32.h | 8 +++ deps/v8/src/mips/ic-mips.cc | 12 ++-- deps/v8/src/mips/lithium-codegen-mips.cc | 7 --- deps/v8/src/mips/lithium-mips.cc | 3 +- deps/v8/src/objects.cc | 2 +- deps/v8/src/string-search.h | 4 ++ deps/v8/src/version.cc | 4 +- deps/v8/src/x64/lithium-codegen-x64.cc | 7 --- deps/v8/src/x64/lithium-gap-resolver-x64.cc | 5 +- deps/v8/src/x64/lithium-x64.cc | 3 +- deps/v8/src/x64/macro-assembler-x64.h | 8 +++ deps/v8/test/cctest/test-api.cc | 84 +++++++++++++++++++++++++- deps/v8/test/mjsunit/regress/regress-108296.js | 52 ++++++++++++++++ 28 files changed, 270 insertions(+), 87 deletions(-) create mode 100644 deps/v8/test/mjsunit/regress/regress-108296.js diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index fecc591..1992b50 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,11 @@ +2011-12-27: Version 3.8.3 + + Avoid embedding new space objects into code objects in the lithium gap + resolver. (chromium:108296) + + Bug fixes and performance optimizations on all platforms. + + 2011-12-21: Version 3.8.2 Add max optimization flag to v8 gyp build to ensure V8 is always built diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 643d0eb..b001eca 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -1938,8 +1938,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement( LOperand* key = needs_write_barrier ? UseTempRegister(instr->key()) : UseRegisterOrConstantAtStart(instr->key()); - - return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); + return new LStoreKeyedFastElement(obj, key, val); } diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index 4b68438..e1e35d2 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -385,6 +385,18 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, } +Handle LCodeGen::ToHandle(LConstantOperand* op) const { + Handle literal = chunk_->LookupLiteral(op); + ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged()); + return literal; +} + + +bool LCodeGen::IsInteger32(LConstantOperand* op) const { + return chunk_->LookupLiteralRepresentation(op).IsInteger32(); +} + + int LCodeGen::ToInteger32(LConstantOperand* op) const { Handle value = chunk_->LookupLiteral(op); ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); @@ -3404,13 +3416,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; Register scratch = scratch0(); - // This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS - // conversion, so it deopts in that case. - if (instr->hydrogen()->ValueNeedsSmiCheck()) { - __ tst(value, Operand(kSmiTagMask)); - DeoptimizeIf(ne, instr->environment()); - } - // Do the store. if (instr->key()->IsConstantOperand()) { ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); diff --git a/deps/v8/src/arm/lithium-codegen-arm.h b/deps/v8/src/arm/lithium-codegen-arm.h index 363449a..e662648 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.h +++ b/deps/v8/src/arm/lithium-codegen-arm.h @@ -93,6 +93,9 @@ class LCodeGen BASE_EMBEDDED { // Returns a MemOperand pointing to the high word of a DoubleStackSlot. MemOperand ToHighMemOperand(LOperand* op) const; + bool IsInteger32(LConstantOperand* op) const; + Handle ToHandle(LConstantOperand* op) const; + // Try to generate code for the entire chunk, but it may fail if the // chunk contains constructs we cannot handle. Returns true if the // code generation attempt succeeded. diff --git a/deps/v8/src/arm/lithium-gap-resolver-arm.cc b/deps/v8/src/arm/lithium-gap-resolver-arm.cc index 26f60fa..ee6cb8e 100644 --- a/deps/v8/src/arm/lithium-gap-resolver-arm.cc +++ b/deps/v8/src/arm/lithium-gap-resolver-arm.cc @@ -248,13 +248,24 @@ void LGapResolver::EmitMove(int index) { } } else if (source->IsConstantOperand()) { - Operand source_operand = cgen_->ToOperand(source); + LConstantOperand* constant_source = LConstantOperand::cast(source); if (destination->IsRegister()) { - __ mov(cgen_->ToRegister(destination), source_operand); + Register dst = cgen_->ToRegister(destination); + if (cgen_->IsInteger32(constant_source)) { + __ mov(dst, Operand(cgen_->ToInteger32(constant_source))); + } else { + __ LoadObject(dst, cgen_->ToHandle(constant_source)); + } } else { ASSERT(destination->IsStackSlot()); ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone. - __ mov(kSavedValueRegister, source_operand); + if (cgen_->IsInteger32(constant_source)) { + __ mov(kSavedValueRegister, + Operand(cgen_->ToInteger32(constant_source))); + } else { + __ LoadObject(kSavedValueRegister, + cgen_->ToHandle(constant_source)); + } __ str(kSavedValueRegister, cgen_->ToMemOperand(destination)); } diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h index 9d74633..392c2f7 100644 --- a/deps/v8/src/arm/macro-assembler-arm.h +++ b/deps/v8/src/arm/macro-assembler-arm.h @@ -168,6 +168,14 @@ class MacroAssembler: public Assembler { void LoadHeapObject(Register dst, Handle object); + void LoadObject(Register result, Handle object) { + if (object->IsHeapObject()) { + LoadHeapObject(result, Handle::cast(object)); + } else { + Move(result, object); + } + } + // --------------------------------------------------------------------------- // GC Support diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc index 1e970e1..24e1782 100644 --- a/deps/v8/src/debug.cc +++ b/deps/v8/src/debug.cc @@ -1146,7 +1146,7 @@ void Debug::SetBreakPoint(Handle shared, Handle debug_info = GetDebugInfo(shared); // Source positions starts with zero. - ASSERT(source_position >= 0); + ASSERT(*source_position >= 0); // Find the break point and change it. BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h index f7fe656..1ae1b17 100644 --- a/deps/v8/src/flag-definitions.h +++ b/deps/v8/src/flag-definitions.h @@ -564,8 +564,10 @@ DEFINE_implication(print_all_code, print_unopt_code) DEFINE_implication(print_all_code, print_code_verbose) DEFINE_implication(print_all_code, print_builtin_code) DEFINE_implication(print_all_code, print_code_stubs) -DEFINE_implication(print_all_code, trace_codegen) DEFINE_implication(print_all_code, code_comments) +#ifdef DEBUG +DEFINE_implication(print_all_code, trace_codegen) +#endif #endif // Cleanup... diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index a3be8ba..5984834 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -463,6 +463,8 @@ void Heap::CollectAllAvailableGarbage() { } mark_compact_collector()->SetFlags(kNoGCFlags); new_space_.Shrink(); + UncommitFromSpace(); + Shrink(); incremental_marking()->UncommitMarkingDeque(); } diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h index fe21c64..1856c80 100644 --- a/deps/v8/src/hydrogen-instructions.h +++ b/deps/v8/src/hydrogen-instructions.h @@ -3933,10 +3933,6 @@ class HStoreKeyedFastElement: public HTemplateInstruction<3> { } } - bool ValueNeedsSmiCheck() { - return value_is_smi(); - } - virtual void PrintDataTo(StringStream* stream); DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement) diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index 617590a..9230870 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -3513,6 +3513,9 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { switch (boilerplate_elements_kind) { case FAST_SMI_ONLY_ELEMENTS: + // Smi-only arrays need a smi check. + AddInstruction(new(zone()) HCheckSmi(value)); + // Fall through. case FAST_ELEMENTS: AddInstruction(new(zone()) HStoreKeyedFastElement( elements, @@ -4223,12 +4226,20 @@ HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, bool is_store) { if (is_store) { ASSERT(val != NULL); - if (elements_kind == FAST_DOUBLE_ELEMENTS) { - return new(zone()) HStoreKeyedFastDoubleElement( - elements, checked_key, val); - } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. - return new(zone()) HStoreKeyedFastElement( - elements, checked_key, val, elements_kind); + switch (elements_kind) { + case FAST_DOUBLE_ELEMENTS: + return new(zone()) HStoreKeyedFastDoubleElement( + elements, checked_key, val); + case FAST_SMI_ONLY_ELEMENTS: + // Smi-only arrays need a smi check. + AddInstruction(new(zone()) HCheckSmi(val)); + // Fall through. + case FAST_ELEMENTS: + return new(zone()) HStoreKeyedFastElement( + elements, checked_key, val, elements_kind); + default: + UNREACHABLE(); + return NULL; } } // It's an element load (!is_store). @@ -4399,9 +4410,6 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, if (elements_kind == FAST_SMI_ONLY_ELEMENTS || elements_kind == FAST_ELEMENTS || elements_kind == FAST_DOUBLE_ELEMENTS) { - if (is_store && elements_kind == FAST_SMI_ONLY_ELEMENTS) { - AddInstruction(new(zone()) HCheckSmi(val)); - } if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) { AddInstruction(new(zone()) HCheckMap( elements, isolate()->factory()->fixed_array_map(), diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index ab38502..137d62c 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -354,18 +354,8 @@ double LCodeGen::ToDouble(LConstantOperand* op) const { } -Immediate LCodeGen::ToImmediate(LOperand* op) { - LConstantOperand* const_op = LConstantOperand::cast(op); - Handle literal = chunk_->LookupLiteral(const_op); - Representation r = chunk_->LookupLiteralRepresentation(const_op); - if (r.IsInteger32()) { - ASSERT(literal->IsNumber()); - return Immediate(static_cast(literal->Number())); - } else if (r.IsDouble()) { - Abort("unsupported double immediate"); - } - ASSERT(r.IsTagged()); - return Immediate(literal); +bool LCodeGen::IsInteger32(LConstantOperand* op) const { + return chunk_->LookupLiteralRepresentation(op).IsInteger32(); } @@ -1167,7 +1157,7 @@ void LCodeGen::DoSubI(LSubI* instr) { ASSERT(left->Equals(instr->result())); if (right->IsConstantOperand()) { - __ sub(ToOperand(left), ToImmediate(right)); + __ sub(ToOperand(left), ToInteger32Immediate(right)); } else { __ sub(ToRegister(left), ToOperand(right)); } @@ -1306,7 +1296,7 @@ void LCodeGen::DoAddI(LAddI* instr) { ASSERT(left->Equals(instr->result())); if (right->IsConstantOperand()) { - __ add(ToOperand(left), ToImmediate(right)); + __ add(ToOperand(left), ToInteger32Immediate(right)); } else { __ add(ToRegister(left), ToOperand(right)); } @@ -1578,9 +1568,9 @@ void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); } else { if (right->IsConstantOperand()) { - __ cmp(ToRegister(left), ToImmediate(right)); + __ cmp(ToRegister(left), ToInteger32Immediate(right)); } else if (left->IsConstantOperand()) { - __ cmp(ToOperand(right), ToImmediate(left)); + __ cmp(ToOperand(right), ToInteger32Immediate(left)); // We transposed the operands. Reverse the condition. cc = ReverseCondition(cc); } else { @@ -3261,7 +3251,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { if (instr->index()->IsConstantOperand()) { __ cmp(ToOperand(instr->length()), - ToImmediate(LConstantOperand::cast(instr->index()))); + Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); DeoptimizeIf(below_equal, instr->environment()); } else { __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); @@ -3315,13 +3305,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { Register elements = ToRegister(instr->object()); Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; - // This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS - // conversion, so it deopts in that case. - if (instr->hydrogen()->ValueNeedsSmiCheck()) { - __ test(value, Immediate(kSmiTagMask)); - DeoptimizeIf(not_zero, instr->environment()); - } - // Do the store. if (instr->key()->IsConstantOperand()) { ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.h b/deps/v8/src/ia32/lithium-codegen-ia32.h index dd335a4..375f137 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.h +++ b/deps/v8/src/ia32/lithium-codegen-ia32.h @@ -78,7 +78,13 @@ class LCodeGen BASE_EMBEDDED { Operand ToOperand(LOperand* op) const; Register ToRegister(LOperand* op) const; XMMRegister ToDoubleRegister(LOperand* op) const; - Immediate ToImmediate(LOperand* op); + + bool IsInteger32(LConstantOperand* op) const; + Immediate ToInteger32Immediate(LOperand* op) const { + return Immediate(ToInteger32(LConstantOperand::cast(op))); + } + + Handle ToHandle(LConstantOperand* op) const; // The operand denoting the second word (the one with a higher address) of // a double stack slot. @@ -225,7 +231,7 @@ class LCodeGen BASE_EMBEDDED { Register ToRegister(int index) const; XMMRegister ToDoubleRegister(int index) const; int ToInteger32(LConstantOperand* op) const; - Handle ToHandle(LConstantOperand* op) const; + double ToDouble(LConstantOperand* op) const; Operand BuildFastArrayOperand(LOperand* elements_pointer, LOperand* key, diff --git a/deps/v8/src/ia32/lithium-gap-resolver-ia32.cc b/deps/v8/src/ia32/lithium-gap-resolver-ia32.cc index fcf1f91..510d9f1 100644 --- a/deps/v8/src/ia32/lithium-gap-resolver-ia32.cc +++ b/deps/v8/src/ia32/lithium-gap-resolver-ia32.cc @@ -303,14 +303,24 @@ void LGapResolver::EmitMove(int index) { } } else if (source->IsConstantOperand()) { - ASSERT(destination->IsRegister() || destination->IsStackSlot()); - Immediate src = cgen_->ToImmediate(source); + LConstantOperand* constant_source = LConstantOperand::cast(source); if (destination->IsRegister()) { Register dst = cgen_->ToRegister(destination); - __ Set(dst, src); + if (cgen_->IsInteger32(constant_source)) { + __ Set(dst, cgen_->ToInteger32Immediate(constant_source)); + } else { + __ LoadObject(dst, cgen_->ToHandle(constant_source)); + } } else { + ASSERT(destination->IsStackSlot()); Operand dst = cgen_->ToOperand(destination); - __ Set(dst, src); + if (cgen_->IsInteger32(constant_source)) { + __ Set(dst, cgen_->ToInteger32Immediate(constant_source)); + } else { + Register tmp = EnsureTempRegister(); + __ LoadObject(tmp, cgen_->ToHandle(constant_source)); + __ mov(dst, tmp); + } } } else if (source->IsDoubleRegister()) { diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc index c503785..5cd276f 100644 --- a/deps/v8/src/ia32/lithium-ia32.cc +++ b/deps/v8/src/ia32/lithium-ia32.cc @@ -2023,8 +2023,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement( LOperand* key = needs_write_barrier ? UseTempRegister(instr->key()) : UseRegisterOrConstantAtStart(instr->key()); - - return AssignEnvironment(new(zone()) LStoreKeyedFastElement(obj, key, val)); + return new(zone()) LStoreKeyedFastElement(obj, key, val); } diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h index 47214ea..e6a1741 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.h +++ b/deps/v8/src/ia32/macro-assembler-ia32.h @@ -240,6 +240,14 @@ class MacroAssembler: public Assembler { void LoadHeapObject(Register result, Handle object); void PushHeapObject(Handle object); + void LoadObject(Register result, Handle object) { + if (object->IsHeapObject()) { + LoadHeapObject(result, Handle::cast(object)); + } else { + Set(result, Immediate(object)); + } + } + // --------------------------------------------------------------------------- // JavaScript invokes diff --git a/deps/v8/src/mips/ic-mips.cc b/deps/v8/src/mips/ic-mips.cc index 1eef55a..8e78488 100644 --- a/deps/v8/src/mips/ic-mips.cc +++ b/deps/v8/src/mips/ic-mips.cc @@ -868,22 +868,26 @@ void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) { // -- lr : return address // ----------------------------------- Label slow, notin; + // Store address is returned in register (of MemOperand) mapped_location. MemOperand mapped_location = GenerateMappedArgumentsLookup(masm, a2, a1, a3, t0, t1, ¬in, &slow); __ sw(a0, mapped_location); - __ Addu(t2, a3, t1); __ mov(t5, a0); - __ RecordWrite(a3, t2, t5, kRAHasNotBeenSaved, kDontSaveFPRegs); + ASSERT_EQ(mapped_location.offset(), 0); + __ RecordWrite(a3, mapped_location.rm(), t5, + kRAHasNotBeenSaved, kDontSaveFPRegs); __ Ret(USE_DELAY_SLOT); __ mov(v0, a0); // (In delay slot) return the value stored in v0. __ bind(¬in); // The unmapped lookup expects that the parameter map is in a3. + // Store address is returned in register (of MemOperand) unmapped_location. MemOperand unmapped_location = GenerateUnmappedArgumentsLookup(masm, a1, a3, t0, &slow); __ sw(a0, unmapped_location); - __ Addu(t2, a3, t0); __ mov(t5, a0); - __ RecordWrite(a3, t2, t5, kRAHasNotBeenSaved, kDontSaveFPRegs); + ASSERT_EQ(unmapped_location.offset(), 0); + __ RecordWrite(a3, unmapped_location.rm(), t5, + kRAHasNotBeenSaved, kDontSaveFPRegs); __ Ret(USE_DELAY_SLOT); __ mov(v0, a0); // (In delay slot) return the value stored in v0. __ bind(&slow); diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc index 895b4c9..53be7d1 100644 --- a/deps/v8/src/mips/lithium-codegen-mips.cc +++ b/deps/v8/src/mips/lithium-codegen-mips.cc @@ -3311,13 +3311,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; Register scratch = scratch0(); - // This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS - // conversion, so it deopts in that case. - if (instr->hydrogen()->ValueNeedsSmiCheck()) { - __ And(at, value, Operand(kSmiTagMask)); - DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); - } - // Do the store. if (instr->key()->IsConstantOperand()) { ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); diff --git a/deps/v8/src/mips/lithium-mips.cc b/deps/v8/src/mips/lithium-mips.cc index 1040b28..634b706 100644 --- a/deps/v8/src/mips/lithium-mips.cc +++ b/deps/v8/src/mips/lithium-mips.cc @@ -1941,8 +1941,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement( LOperand* key = needs_write_barrier ? UseTempRegister(instr->key()) : UseRegisterOrConstantAtStart(instr->key()); - - return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); + return new LStoreKeyedFastElement(obj, key, val); } diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index e193188..ae5aa78 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -4352,7 +4352,7 @@ MaybeObject* JSObject::DefineGetterSetter(String* name, } else { // Lookup the name. LookupResult result(heap->isolate()); - LocalLookup(name, &result); + LocalLookupRealNamedProperty(name, &result); if (result.IsProperty()) { // TODO(mstarzinger): We should check for result.IsDontDelete() here once // we only call into the runtime once to set both getter and setter. diff --git a/deps/v8/src/string-search.h b/deps/v8/src/string-search.h index f540583..8c3456a 100644 --- a/deps/v8/src/string-search.h +++ b/deps/v8/src/string-search.h @@ -369,6 +369,10 @@ void StringSearch::PopulateBoyerMooreTable() { shift_table[pattern_length] = 1; suffix_table[pattern_length] = pattern_length + 1; + if (pattern_length <= start) { + return; + } + // Find suffixes. PatternChar last_char = pattern[pattern_length - 1]; int suffix = pattern_length + 1; diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index 5adcde8..0b296c0 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -34,8 +34,8 @@ // cannot be changed without changing the SCons build script. #define MAJOR_VERSION 3 #define MINOR_VERSION 8 -#define BUILD_NUMBER 2 -#define PATCH_LEVEL 1 +#define BUILD_NUMBER 3 +#define PATCH_LEVEL 0 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) #define IS_CANDIDATE_VERSION 0 diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc index 70f5874..6239acb 100644 --- a/deps/v8/src/x64/lithium-codegen-x64.cc +++ b/deps/v8/src/x64/lithium-codegen-x64.cc @@ -3200,13 +3200,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { Register elements = ToRegister(instr->object()); Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; - // This instruction cannot handle the FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS - // conversion, so it deopts in that case. - if (instr->hydrogen()->ValueNeedsSmiCheck()) { - Condition cc = masm()->CheckSmi(value); - DeoptimizeIf(NegateCondition(cc), instr->environment()); - } - // Do the store. if (instr->key()->IsConstantOperand()) { ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); diff --git a/deps/v8/src/x64/lithium-gap-resolver-x64.cc b/deps/v8/src/x64/lithium-gap-resolver-x64.cc index c3c617c..bf5d31d 100644 --- a/deps/v8/src/x64/lithium-gap-resolver-x64.cc +++ b/deps/v8/src/x64/lithium-gap-resolver-x64.cc @@ -198,7 +198,7 @@ void LGapResolver::EmitMove(int index) { if (cgen_->IsInteger32Constant(constant_source)) { __ movl(dst, Immediate(cgen_->ToInteger32(constant_source))); } else { - __ Move(dst, cgen_->ToHandle(constant_source)); + __ LoadObject(dst, cgen_->ToHandle(constant_source)); } } else { ASSERT(destination->IsStackSlot()); @@ -207,7 +207,8 @@ void LGapResolver::EmitMove(int index) { // Allow top 32 bits of an untagged Integer32 to be arbitrary. __ movl(dst, Immediate(cgen_->ToInteger32(constant_source))); } else { - __ Move(dst, cgen_->ToHandle(constant_source)); + __ LoadObject(kScratchRegister, cgen_->ToHandle(constant_source)); + __ movq(dst, kScratchRegister); } } diff --git a/deps/v8/src/x64/lithium-x64.cc b/deps/v8/src/x64/lithium-x64.cc index ac4d5f5..5bae14b 100644 --- a/deps/v8/src/x64/lithium-x64.cc +++ b/deps/v8/src/x64/lithium-x64.cc @@ -1929,8 +1929,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement( LOperand* key = needs_write_barrier ? UseTempRegister(instr->key()) : UseRegisterOrConstantAtStart(instr->key()); - - return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); + return new LStoreKeyedFastElement(obj, key, val); } diff --git a/deps/v8/src/x64/macro-assembler-x64.h b/deps/v8/src/x64/macro-assembler-x64.h index 8046e5c..97a9801 100644 --- a/deps/v8/src/x64/macro-assembler-x64.h +++ b/deps/v8/src/x64/macro-assembler-x64.h @@ -789,6 +789,14 @@ class MacroAssembler: public Assembler { void LoadHeapObject(Register result, Handle object); void PushHeapObject(Handle object); + void LoadObject(Register result, Handle object) { + if (object->IsHeapObject()) { + LoadHeapObject(result, Handle::cast(object)); + } else { + Move(result, object); + } + } + // Load a global cell into a register. void LoadGlobalCell(Register dst, Handle cell); diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 8b618d4..dab8b7c 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -1423,6 +1423,40 @@ THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) { THREADED_TEST(SwitchFromInterceptorToAccessor) { v8::HandleScope scope; + Handle templ = FunctionTemplate::New(); + AddAccessor(templ, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "function setAge(i){ obj.age = i; };" + "for(var i = 0; i <= 10000; i++) setAge(i);"); + // All i < 10000 go to the interceptor. + ExpectInt32("obj.interceptor_age", 9999); + // The last i goes to the accessor. + ExpectInt32("obj.accessor_age", 10000); +} + +THREADED_TEST(SwitchFromAccessorToInterceptor) { + v8::HandleScope scope; + Handle templ = FunctionTemplate::New(); + AddAccessor(templ, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "function setAge(i){ obj.age = i; };" + "for(var i = 20000; i >= 9999; i--) setAge(i);"); + // All i >= 10000 go to the accessor. + ExpectInt32("obj.accessor_age", 10000); + // The last i goes to the interceptor. + ExpectInt32("obj.interceptor_age", 9999); +} + +THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) { + v8::HandleScope scope; Handle parent = FunctionTemplate::New(); Handle child = FunctionTemplate::New(); child->Inherit(parent); @@ -1440,7 +1474,7 @@ THREADED_TEST(SwitchFromInterceptorToAccessor) { ExpectInt32("child.accessor_age", 10000); } -THREADED_TEST(SwitchFromAccessorToInterceptor) { +THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) { v8::HandleScope scope; Handle parent = FunctionTemplate::New(); Handle child = FunctionTemplate::New(); @@ -1459,6 +1493,54 @@ THREADED_TEST(SwitchFromAccessorToInterceptor) { ExpectInt32("child.interceptor_age", 9999); } +THREADED_TEST(SwitchFromInterceptorToJSAccessor) { + v8::HandleScope scope; + Handle templ = FunctionTemplate::New(); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "function setter(i) { this.accessor_age = i; };" + "function getter() { return this.accessor_age; };" + "function setAge(i) { obj.age = i; };" + "Object.defineProperty(obj, 'age', { get:getter, set:setter });" + "for(var i = 0; i <= 10000; i++) setAge(i);"); + // All i < 10000 go to the interceptor. + ExpectInt32("obj.interceptor_age", 9999); + // The last i goes to the JavaScript accessor. + ExpectInt32("obj.accessor_age", 10000); + // The installed JavaScript getter is still intact. + // This last part is a regression test for issue 1651 and relies on the fact + // that both interceptor and accessor are being installed on the same object. + ExpectInt32("obj.age", 10000); + ExpectBoolean("obj.hasOwnProperty('age')", true); + ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value"); +} + +THREADED_TEST(SwitchFromJSAccessorToInterceptor) { + v8::HandleScope scope; + Handle templ = FunctionTemplate::New(); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "function setter(i) { this.accessor_age = i; };" + "function getter() { return this.accessor_age; };" + "function setAge(i) { obj.age = i; };" + "Object.defineProperty(obj, 'age', { get:getter, set:setter });" + "for(var i = 20000; i >= 9999; i--) setAge(i);"); + // All i >= 10000 go to the accessor. + ExpectInt32("obj.accessor_age", 10000); + // The last i goes to the interceptor. + ExpectInt32("obj.interceptor_age", 9999); + // The installed JavaScript getter is still intact. + // This last part is a regression test for issue 1651 and relies on the fact + // that both interceptor and accessor are being installed on the same object. + ExpectInt32("obj.age", 10000); + ExpectBoolean("obj.hasOwnProperty('age')", true); + ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value"); +} + THREADED_TEST(SwitchFromInterceptorToProperty) { v8::HandleScope scope; Handle parent = FunctionTemplate::New(); diff --git a/deps/v8/test/mjsunit/regress/regress-108296.js b/deps/v8/test/mjsunit/regress/regress-108296.js new file mode 100644 index 0000000..38ecda7 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-108296.js @@ -0,0 +1,52 @@ +// 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: +// +// * 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. + +// Flags: --allow-natives-syntax + +// This test checks that young immediates embedded into code objects +// are referenced through a cell. + +function f (k, a, b) { + // Create control flow for a.foo. Control flow resolution will + // be generated as a part of a gap move. Gap move operate on immediates as + // a.foo is a CONSTANT_FUNCTION. + var x = k ? a.foo : a.foo; + return x.prototype; +} + +var a = { }; + +// Make sure that foo is a CONSTANT_FUNCTION but not be pretenured. +a.foo = (function () { return function () {}; })(); + +// Ensure that both branches of ternary operator have monomorphic type feedback. +f(true, a, a); +f(true, a, a); +f(false, a, a); +f(false, a, a); +%OptimizeFunctionOnNextCall(f); +f(true, a, a); -- 2.7.4