diff options
author | Trevor Norris <trev.norris@gmail.com> | 2014-04-01 11:46:28 -0700 |
---|---|---|
committer | Trevor Norris <trev.norris@gmail.com> | 2014-04-01 11:46:28 -0700 |
commit | 8d6fa72d9720963387b73e0770eeec4dd0ba6dce (patch) | |
tree | 86b419d65b09d0b2b3e50a67c5f19dcbba268117 /deps | |
parent | 490d5ab7808aedb998d1f4f933bf3de748758f62 (diff) | |
download | node-new-8d6fa72d9720963387b73e0770eeec4dd0ba6dce.tar.gz |
v8: upgrade to 3.24.35.22
Diffstat (limited to 'deps')
36 files changed, 529 insertions, 152 deletions
diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 1560e71637..fe3b020417 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -131,7 +131,6 @@ template<class T, class P> class WeakCallbackObject; class FunctionTemplate; class ObjectTemplate; class Data; -template<typename T> class FunctionCallbackInfo; template<typename T> class PropertyCallbackInfo; class StackTrace; class StackFrame; diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 7a412df28d..54a3e9145d 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -5805,20 +5805,7 @@ void v8::ArrayBuffer::Neuter() { "Only externalized ArrayBuffers can be neutered"); LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()"); ENTER_V8(isolate); - - for (i::Handle<i::Object> view_obj(obj->weak_first_view(), isolate); - !view_obj->IsUndefined();) { - i::Handle<i::JSArrayBufferView> view(i::JSArrayBufferView::cast(*view_obj)); - if (view->IsJSTypedArray()) { - i::JSTypedArray::cast(*view)->Neuter(); - } else if (view->IsJSDataView()) { - i::JSDataView::cast(*view)->Neuter(); - } else { - UNREACHABLE(); - } - view_obj = i::handle(view->weak_next(), isolate); - } - obj->Neuter(); + i::Runtime::NeuterArrayBuffer(obj); } diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 38509a6ea8..fcd7d3c9a3 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -614,15 +614,6 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, instr->MarkAsCall(); instr = AssignPointerMap(instr); - if (hinstr->HasObservableSideEffects()) { - ASSERT(hinstr->next()->IsSimulate()); - HSimulate* sim = HSimulate::cast(hinstr->next()); - ASSERT(instruction_pending_deoptimization_environment_ == NULL); - ASSERT(pending_deoptimization_ast_id_.IsNone()); - instruction_pending_deoptimization_environment_ = instr; - pending_deoptimization_ast_id_ = sim->ast_id(); - } - // If instruction does not have side-effects lazy deoptimization // after the call will try to deoptimize to the point before the call. // Thus we still need to attach environment to this call even if @@ -906,6 +897,26 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) { instr = AssignEnvironment(instr); } chunk_->AddInstruction(instr, current_block_); + + if (instr->IsCall()) { + HValue* hydrogen_value_for_lazy_bailout = current; + LInstruction* instruction_needing_environment = NULL; + if (current->HasObservableSideEffects()) { + HSimulate* sim = HSimulate::cast(current->next()); + instruction_needing_environment = instr; + sim->ReplayEnvironment(current_block_->last_environment()); + hydrogen_value_for_lazy_bailout = sim; + } + LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout()); + bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); + chunk_->AddInstruction(bailout, current_block_); + if (instruction_needing_environment != NULL) { + // Store the lazy deopt environment with the instruction if needed. + // Right now it is only used for LInstanceOfKnownGlobal. + instruction_needing_environment-> + SetDeferredLazyDeoptimizationEnvironment(bailout->environment()); + } + } } current_instruction_ = old_current; } @@ -2378,21 +2389,6 @@ LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { instr->ReplayEnvironment(current_block_->last_environment()); - - // If there is an instruction pending deoptimization environment create a - // lazy bailout instruction to capture the environment. - if (pending_deoptimization_ast_id_ == instr->ast_id()) { - LInstruction* result = new(zone()) LLazyBailout; - result = AssignEnvironment(result); - // Store the lazy deopt environment with the instruction if needed. Right - // now it is only used for LInstanceOfKnownGlobal. - instruction_pending_deoptimization_environment_-> - SetDeferredLazyDeoptimizationEnvironment(result->environment()); - instruction_pending_deoptimization_environment_ = NULL; - pending_deoptimization_ast_id_ = BailoutId::None(); - return result; - } - return NULL; } diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index 05348bf018..cfcc56da29 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -269,6 +269,13 @@ void LCodeGen::GenerateOsrPrologue() { } +void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { + if (!instr->IsLazyBailout() && !instr->IsGap()) { + safepoints_.BumpLastLazySafepointIndex(); + } +} + + bool LCodeGen::GenerateDeferredCode() { ASSERT(is_generating()); if (deferred_.length() > 0) { @@ -2112,7 +2119,6 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) { // is in the correct position. Assembler::BlockConstPoolScope block_const_pool(masm()); CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); - __ nop(); // Signals no inlined code. } @@ -4402,7 +4408,8 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { this, Safepoint::kWithRegistersAndDoubles); __ Move(r0, object_reg); __ Move(r1, to_map); - TransitionElementsKindStub stub(from_kind, to_kind); + bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; + TransitionElementsKindStub stub(from_kind, to_kind, is_js_array); __ CallStub(&stub); RecordSafepointWithRegistersAndDoubles( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); diff --git a/deps/v8/src/arm/lithium-codegen-arm.h b/deps/v8/src/arm/lithium-codegen-arm.h index 5251b85fa9..d58c18f6c9 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.h +++ b/deps/v8/src/arm/lithium-codegen-arm.h @@ -191,6 +191,7 @@ class LCodeGen: public LCodeGenBase { // Code generation passes. Returns true if code generation should // continue. + void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE; bool GeneratePrologue(); bool GenerateDeferredCode(); bool GenerateDeoptJumpTable(); diff --git a/deps/v8/src/arraybuffer.js b/deps/v8/src/arraybuffer.js index cfaa8d7efc..d5fd9adbad 100644 --- a/deps/v8/src/arraybuffer.js +++ b/deps/v8/src/arraybuffer.js @@ -56,6 +56,9 @@ function ArrayBufferSlice(start, end) { } var relativeStart = TO_INTEGER(start); + if (!IS_UNDEFINED(end)) { + end = TO_INTEGER(end); + } var first; var byte_length = %ArrayBufferGetByteLength(this); if (relativeStart < 0) { @@ -63,7 +66,7 @@ function ArrayBufferSlice(start, end) { } else { first = MathMin(relativeStart, byte_length); } - var relativeEnd = IS_UNDEFINED(end) ? byte_length : TO_INTEGER(end); + var relativeEnd = IS_UNDEFINED(end) ? byte_length : end; var fin; if (relativeEnd < 0) { fin = MathMax(byte_length + relativeEnd, 0); diff --git a/deps/v8/src/code-stubs-hydrogen.cc b/deps/v8/src/code-stubs-hydrogen.cc index 638f9e5a1d..455d087684 100644 --- a/deps/v8/src/code-stubs-hydrogen.cc +++ b/deps/v8/src/code-stubs-hydrogen.cc @@ -618,7 +618,7 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() { GetParameter(1), casted_stub()->from_kind(), casted_stub()->to_kind(), - true); + casted_stub()->is_js_array()); return GetParameter(0); } diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h index a7283ba642..8d283d9e39 100644 --- a/deps/v8/src/code-stubs.h +++ b/deps/v8/src/code-stubs.h @@ -2009,9 +2009,11 @@ class KeyedStoreFastElementStub : public HydrogenCodeStub { class TransitionElementsKindStub : public HydrogenCodeStub { public: TransitionElementsKindStub(ElementsKind from_kind, - ElementsKind to_kind) { + ElementsKind to_kind, + bool is_js_array) { bit_field_ = FromKindBits::encode(from_kind) | - ToKindBits::encode(to_kind); + ToKindBits::encode(to_kind) | + IsJSArrayBits::encode(is_js_array); } ElementsKind from_kind() const { @@ -2022,6 +2024,10 @@ class TransitionElementsKindStub : public HydrogenCodeStub { return ToKindBits::decode(bit_field_); } + bool is_js_array() const { + return IsJSArrayBits::decode(bit_field_); + } + virtual Handle<Code> GenerateCode(Isolate* isolate); virtual void InitializeInterfaceDescriptor( @@ -2031,6 +2037,7 @@ class TransitionElementsKindStub : public HydrogenCodeStub { private: class FromKindBits: public BitField<ElementsKind, 8, 8> {}; class ToKindBits: public BitField<ElementsKind, 0, 8> {}; + class IsJSArrayBits: public BitField<bool, 16, 1> {}; uint32_t bit_field_; Major MajorKey() { return TransitionElementsKind; } diff --git a/deps/v8/src/deoptimizer.cc b/deps/v8/src/deoptimizer.cc index 18be014c14..29575d8c00 100644 --- a/deps/v8/src/deoptimizer.cc +++ b/deps/v8/src/deoptimizer.cc @@ -393,9 +393,33 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) { element = next; } +#ifdef DEBUG + // Make sure all activations of optimized code can deopt at their current PC. + for (StackFrameIterator it(isolate, isolate->thread_local_top()); + !it.done(); it.Advance()) { + StackFrame::Type type = it.frame()->type(); + if (type == StackFrame::OPTIMIZED) { + Code* code = it.frame()->LookupCode(); + if (FLAG_trace_deopt) { + JSFunction* function = + static_cast<OptimizedFrame*>(it.frame())->function(); + CodeTracer::Scope scope(isolate->GetCodeTracer()); + PrintF(scope.file(), "[deoptimizer patches for lazy deopt: "); + function->PrintName(scope.file()); + PrintF(scope.file(), + " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function)); + } + SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc()); + int deopt_index = safepoint.deoptimization_index(); + CHECK(deopt_index != Safepoint::kNoDeoptimizationIndex); + } + } +#endif + // TODO(titzer): we need a handle scope only because of the macro assembler, // which is only used in EnsureCodeForDeoptimizationEntry. HandleScope scope(isolate); + // Now patch all the codes for deoptimization. for (int i = 0; i < codes.length(); i++) { // It is finally time to die, code object. diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index dfe98ec080..82cf45f742 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -590,6 +590,9 @@ void Heap::GarbageCollectionEpilogue() { if (FLAG_code_stats) ReportCodeStatistics("After GC"); #endif if (FLAG_deopt_every_n_garbage_collections > 0) { + // TODO(jkummerow/ulan/jarin): This is not safe! We can't assume that + // the topmost optimized frame can be deoptimized safely, because it + // might not have a lazy bailout point right after its current PC. if (++gcs_since_last_deopt_ == FLAG_deopt_every_n_garbage_collections) { Deoptimizer::DeoptimizeAll(isolate()); gcs_since_last_deopt_ = 0; diff --git a/deps/v8/src/hydrogen-bce.cc b/deps/v8/src/hydrogen-bce.cc index e1a2847127..c98a03cb5a 100644 --- a/deps/v8/src/hydrogen-bce.cc +++ b/deps/v8/src/hydrogen-bce.cc @@ -132,6 +132,24 @@ class BoundsCheckBbData: public ZoneObject { bool HasSingleCheck() { return lower_check_ == upper_check_; } + void UpdateUpperOffsets(HBoundsCheck* check, int32_t offset) { + BoundsCheckBbData* data = FatherInDominatorTree(); + while (data != NULL && data->UpperCheck() == check) { + ASSERT(data->upper_offset_ <= offset); + data->upper_offset_ = offset; + data = data->FatherInDominatorTree(); + } + } + + void UpdateLowerOffsets(HBoundsCheck* check, int32_t offset) { + BoundsCheckBbData* data = FatherInDominatorTree(); + while (data != NULL && data->LowerCheck() == check) { + ASSERT(data->lower_offset_ > offset); + data->lower_offset_ = offset; + data = data->FatherInDominatorTree(); + } + } + // The goal of this method is to modify either upper_offset_ or // lower_offset_ so that also new_offset is covered (the covered // range grows). @@ -156,6 +174,7 @@ class BoundsCheckBbData: public ZoneObject { upper_check_ = new_check; } else { TightenCheck(upper_check_, new_check); + UpdateUpperOffsets(upper_check_, upper_offset_); } } else if (new_offset < lower_offset_) { lower_offset_ = new_offset; @@ -164,6 +183,7 @@ class BoundsCheckBbData: public ZoneObject { lower_check_ = new_check; } else { TightenCheck(lower_check_, new_check); + UpdateLowerOffsets(lower_check_, lower_offset_); } } else { // Should never have called CoverCheck() in this case. diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc index b14873eb62..2ca0c54a55 100644 --- a/deps/v8/src/hydrogen-instructions.cc +++ b/deps/v8/src/hydrogen-instructions.cc @@ -2413,6 +2413,7 @@ void HSimulate::PrintDataTo(StringStream* stream) { void HSimulate::ReplayEnvironment(HEnvironment* env) { + if (done_with_replay_) return; ASSERT(env != NULL); env->set_ast_id(ast_id()); env->Drop(pop_count()); @@ -2424,6 +2425,7 @@ void HSimulate::ReplayEnvironment(HEnvironment* env) { env->Push(value); } } + done_with_replay_ = true; } diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h index f897e91bb3..a62f3cebf2 100644 --- a/deps/v8/src/hydrogen-instructions.h +++ b/deps/v8/src/hydrogen-instructions.h @@ -1799,7 +1799,8 @@ class HSimulate V8_FINAL : public HInstruction { values_(2, zone), assigned_indexes_(2, zone), zone_(zone), - removable_(removable) {} + removable_(removable), + done_with_replay_(false) {} ~HSimulate() {} virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; @@ -1882,7 +1883,8 @@ class HSimulate V8_FINAL : public HInstruction { ZoneList<HValue*> values_; ZoneList<int> assigned_indexes_; Zone* zone_; - RemovableSimulate removable_; + RemovableSimulate removable_ : 2; + bool done_with_replay_ : 1; #ifdef DEBUG Handle<JSFunction> closure_; diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index 7ee8180cca..16096ccf9f 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -9764,6 +9764,15 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( HInstruction* object = Add<HAllocate>(object_size_constant, type, pretenure_flag, instance_type, site_context->current()); + // If allocation folding reaches Page::kMaxRegularHeapObjectSize the + // elements array may not get folded into the object. Hence, we set the + // elements pointer to empty fixed array and let store elimination remove + // this store in the folding case. + HConstant* empty_fixed_array = Add<HConstant>( + isolate()->factory()->empty_fixed_array()); + Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), + empty_fixed_array, INITIALIZING_STORE); + BuildEmitObjectHeader(boilerplate_object, object); Handle<FixedArrayBase> elements(boilerplate_object->elements()); diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index f9d1fc0d25..5a12ca9690 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -390,6 +390,9 @@ void LCodeGen::GenerateOsrPrologue() { void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { + if (!instr->IsLazyBailout() && !instr->IsGap()) { + safepoints_.BumpLastLazySafepointIndex(); + } if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr); } @@ -2274,7 +2277,6 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) { BinaryOpICStub stub(instr->op(), NO_OVERWRITE); CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); - __ nop(); // Signals no inlined code. } @@ -4696,7 +4698,8 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { __ mov(eax, object_reg); } __ mov(ebx, to_map); - TransitionElementsKindStub stub(from_kind, to_kind); + bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; + TransitionElementsKindStub stub(from_kind, to_kind, is_js_array); __ CallStub(&stub); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc index 27a5672901..a9d49205ce 100644 --- a/deps/v8/src/ia32/lithium-ia32.cc +++ b/deps/v8/src/ia32/lithium-ia32.cc @@ -679,15 +679,6 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, instr->MarkAsCall(); instr = AssignPointerMap(instr); - if (hinstr->HasObservableSideEffects()) { - ASSERT(hinstr->next()->IsSimulate()); - HSimulate* sim = HSimulate::cast(hinstr->next()); - ASSERT(instruction_pending_deoptimization_environment_ == NULL); - ASSERT(pending_deoptimization_ast_id_.IsNone()); - instruction_pending_deoptimization_environment_ = instr; - pending_deoptimization_ast_id_ = sim->ast_id(); - } - // If instruction does not have side-effects lazy deoptimization // after the call will try to deoptimize to the point before the call. // Thus we still need to attach environment to this call even if @@ -980,6 +971,26 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) { chunk_->AddInstruction(clobber, current_block_); } chunk_->AddInstruction(instr, current_block_); + + if (instr->IsCall()) { + HValue* hydrogen_value_for_lazy_bailout = current; + LInstruction* instruction_needing_environment = NULL; + if (current->HasObservableSideEffects()) { + HSimulate* sim = HSimulate::cast(current->next()); + instruction_needing_environment = instr; + sim->ReplayEnvironment(current_block_->last_environment()); + hydrogen_value_for_lazy_bailout = sim; + } + LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout()); + bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); + chunk_->AddInstruction(bailout, current_block_); + if (instruction_needing_environment != NULL) { + // Store the lazy deopt environment with the instruction if needed. + // Right now it is only used for LInstanceOfKnownGlobal. + instruction_needing_environment-> + SetDeferredLazyDeoptimizationEnvironment(bailout->environment()); + } + } } current_instruction_ = old_current; } @@ -2486,22 +2497,6 @@ LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { instr->ReplayEnvironment(current_block_->last_environment()); - - // If there is an instruction pending deoptimization environment create a - // lazy bailout instruction to capture the environment. - if (!pending_deoptimization_ast_id_.IsNone()) { - ASSERT(pending_deoptimization_ast_id_ == instr->ast_id()); - LLazyBailout* lazy_bailout = new(zone()) LLazyBailout; - LInstruction* result = AssignEnvironment(lazy_bailout); - // Store the lazy deopt environment with the instruction if needed. Right - // now it is only used for LInstanceOfKnownGlobal. - instruction_pending_deoptimization_environment_-> - SetDeferredLazyDeoptimizationEnvironment(result->environment()); - instruction_pending_deoptimization_environment_ = NULL; - pending_deoptimization_ast_id_ = BailoutId::None(); - return result; - } - return NULL; } diff --git a/deps/v8/src/ia32/lithium-ia32.h b/deps/v8/src/ia32/lithium-ia32.h index 811700a544..a36cf413e3 100644 --- a/deps/v8/src/ia32/lithium-ia32.h +++ b/deps/v8/src/ia32/lithium-ia32.h @@ -2591,9 +2591,7 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { current_instruction_(NULL), current_block_(NULL), next_block_(NULL), - allocator_(allocator), - instruction_pending_deoptimization_environment_(NULL), - pending_deoptimization_ast_id_(BailoutId::None()) { } + allocator_(allocator) { } // Build the sequence for the graph. LPlatformChunk* Build(); @@ -2736,8 +2734,6 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { HBasicBlock* current_block_; HBasicBlock* next_block_; LAllocator* allocator_; - LInstruction* instruction_pending_deoptimization_environment_; - BailoutId pending_deoptimization_ast_id_; DISALLOW_COPY_AND_ASSIGN(LChunkBuilder); }; diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc index d34344c83f..f033f6d348 100644 --- a/deps/v8/src/mips/lithium-codegen-mips.cc +++ b/deps/v8/src/mips/lithium-codegen-mips.cc @@ -259,6 +259,13 @@ void LCodeGen::GenerateOsrPrologue() { } +void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { + if (!instr->IsLazyBailout() && !instr->IsGap()) { + safepoints_.BumpLastLazySafepointIndex(); + } +} + + bool LCodeGen::GenerateDeferredCode() { ASSERT(is_generating()); if (deferred_.length() > 0) { @@ -4336,7 +4343,8 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { this, Safepoint::kWithRegistersAndDoubles); __ mov(a0, object_reg); __ li(a1, Operand(to_map)); - TransitionElementsKindStub stub(from_kind, to_kind); + bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; + TransitionElementsKindStub stub(from_kind, to_kind, is_js_array); __ CallStub(&stub); RecordSafepointWithRegistersAndDoubles( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); diff --git a/deps/v8/src/mips/lithium-codegen-mips.h b/deps/v8/src/mips/lithium-codegen-mips.h index b4651702e0..1e572bc95f 100644 --- a/deps/v8/src/mips/lithium-codegen-mips.h +++ b/deps/v8/src/mips/lithium-codegen-mips.h @@ -191,6 +191,7 @@ class LCodeGen: public LCodeGenBase { // Code generation passes. Returns true if code generation should // continue. + void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE; bool GeneratePrologue(); bool GenerateDeferredCode(); bool GenerateDeoptJumpTable(); diff --git a/deps/v8/src/mips/lithium-mips.cc b/deps/v8/src/mips/lithium-mips.cc index bb8e7502d8..d423040a0d 100644 --- a/deps/v8/src/mips/lithium-mips.cc +++ b/deps/v8/src/mips/lithium-mips.cc @@ -619,15 +619,6 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, instr->MarkAsCall(); instr = AssignPointerMap(instr); - if (hinstr->HasObservableSideEffects()) { - ASSERT(hinstr->next()->IsSimulate()); - HSimulate* sim = HSimulate::cast(hinstr->next()); - ASSERT(instruction_pending_deoptimization_environment_ == NULL); - ASSERT(pending_deoptimization_ast_id_.IsNone()); - instruction_pending_deoptimization_environment_ = instr; - pending_deoptimization_ast_id_ = sim->ast_id(); - } - // If instruction does not have side-effects lazy deoptimization // after the call will try to deoptimize to the point before the call. // Thus we still need to attach environment to this call even if @@ -914,6 +905,26 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) { instr = AssignEnvironment(instr); } chunk_->AddInstruction(instr, current_block_); + + if (instr->IsCall()) { + HValue* hydrogen_value_for_lazy_bailout = current; + LInstruction* instruction_needing_environment = NULL; + if (current->HasObservableSideEffects()) { + HSimulate* sim = HSimulate::cast(current->next()); + instruction_needing_environment = instr; + sim->ReplayEnvironment(current_block_->last_environment()); + hydrogen_value_for_lazy_bailout = sim; + } + LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout()); + bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); + chunk_->AddInstruction(bailout, current_block_); + if (instruction_needing_environment != NULL) { + // Store the lazy deopt environment with the instruction if needed. + // Right now it is only used for LInstanceOfKnownGlobal. + instruction_needing_environment-> + SetDeferredLazyDeoptimizationEnvironment(bailout->environment()); + } + } } current_instruction_ = old_current; } @@ -2307,21 +2318,6 @@ LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { instr->ReplayEnvironment(current_block_->last_environment()); - - // If there is an instruction pending deoptimization environment create a - // lazy bailout instruction to capture the environment. - if (pending_deoptimization_ast_id_ == instr->ast_id()) { - LInstruction* result = new(zone()) LLazyBailout; - result = AssignEnvironment(result); - // Store the lazy deopt environment with the instruction if needed. Right - // now it is only used for LInstanceOfKnownGlobal. - instruction_pending_deoptimization_environment_-> - SetDeferredLazyDeoptimizationEnvironment(result->environment()); - instruction_pending_deoptimization_environment_ = NULL; - pending_deoptimization_ast_id_ = BailoutId::None(); - return result; - } - return NULL; } diff --git a/deps/v8/src/mips/lithium-mips.h b/deps/v8/src/mips/lithium-mips.h index 6cc13bf4c2..39e2691849 100644 --- a/deps/v8/src/mips/lithium-mips.h +++ b/deps/v8/src/mips/lithium-mips.h @@ -2554,9 +2554,7 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { current_block_(NULL), next_block_(NULL), allocator_(allocator), - position_(RelocInfo::kNoPosition), - instruction_pending_deoptimization_environment_(NULL), - pending_deoptimization_ast_id_(BailoutId::None()) { } + position_(RelocInfo::kNoPosition) { } // Build the sequence for the graph. LPlatformChunk* Build(); @@ -2691,8 +2689,6 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { HBasicBlock* next_block_; LAllocator* allocator_; int position_; - LInstruction* instruction_pending_deoptimization_environment_; - BailoutId pending_deoptimization_ast_id_; DISALLOW_COPY_AND_ASSIGN(LChunkBuilder); }; diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index ac9a2c0c9e..422da34e7f 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -796,6 +796,24 @@ bool Runtime::SetupArrayBufferAllocatingData( } +void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) { + Isolate* isolate = array_buffer->GetIsolate(); + for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate); + !view_obj->IsUndefined();) { + Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj)); + if (view->IsJSTypedArray()) { + JSTypedArray::cast(*view)->Neuter(); + } else if (view->IsJSDataView()) { + JSDataView::cast(*view)->Neuter(); + } else { + UNREACHABLE(); + } + view_obj = handle(view->weak_next(), isolate); + } + array_buffer->Neuter(); +} + + RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) { HandleScope scope(isolate); ASSERT(args.length() == 2); @@ -849,7 +867,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) { if (target_length == 0) return isolate->heap()->undefined_value(); - ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start); + size_t source_byte_length = NumberToSize(isolate, source->byte_length()); + CHECK(start <= source_byte_length); + CHECK(source_byte_length - start >= target_length); uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store()); uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store()); CopyBytes(target_data, source_data + start, target_length); @@ -867,6 +887,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) { } +RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferNeuter) { + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0); + ASSERT(!array_buffer->is_external()); + void* backing_store = array_buffer->backing_store(); + size_t byte_length = NumberToSize(isolate, array_buffer->byte_length()); + array_buffer->set_is_external(true); + Runtime::NeuterArrayBuffer(array_buffer); + V8::ArrayBufferAllocator()->Free(backing_store, byte_length); + return isolate->heap()->undefined_value(); +} + + void Runtime::ArrayIdToTypeAndSize( int arrayId, ExternalArrayType* array_type, size_t* element_size) { switch (arrayId) { @@ -910,7 +943,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { size_t byte_offset = NumberToSize(isolate, *byte_offset_object); size_t byte_length = NumberToSize(isolate, *byte_length_object); - ASSERT(byte_length % element_size == 0); + size_t array_buffer_byte_length = + NumberToSize(isolate, buffer->byte_length()); + CHECK(byte_offset <= array_buffer_byte_length); + CHECK(array_buffer_byte_length - byte_offset >= byte_length); + + CHECK_EQ(0, static_cast<int>(byte_length % element_size)); size_t length = byte_length / element_size; if (length > static_cast<unsigned>(Smi::kMaxValue)) { @@ -1645,6 +1683,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) { ASSERT(args.length() == 2); CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); + if (obj->IsAccessCheckNeeded() && + !isolate->MayNamedAccessWrapper(obj, + isolate->factory()->proto_string(), + v8::ACCESS_SET)) { + isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_SET); + RETURN_IF_SCHEDULED_EXCEPTION(isolate); + return isolate->heap()->undefined_value(); + } if (FLAG_harmony_observation && obj->map()->is_observed()) { Handle<Object> old_value( GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate); diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h index 61c019c068..0506e9d86d 100644 --- a/deps/v8/src/runtime.h +++ b/deps/v8/src/runtime.h @@ -365,6 +365,7 @@ namespace internal { F(ArrayBufferGetByteLength, 1, 1)\ F(ArrayBufferSliceImpl, 3, 1) \ F(ArrayBufferIsView, 1, 1) \ + F(ArrayBufferNeuter, 1, 1) \ \ F(TypedArrayInitialize, 5, 1) \ F(TypedArrayInitializeFromArrayLike, 4, 1) \ @@ -827,6 +828,8 @@ class Runtime : public AllStatic { size_t allocated_length, bool initialize = true); + static void NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer); + static void FreeArrayBuffer( Isolate* isolate, JSArrayBuffer* phantom_array_buffer); diff --git a/deps/v8/src/safepoint-table.h b/deps/v8/src/safepoint-table.h index ea35253ff8..cd094c55bf 100644 --- a/deps/v8/src/safepoint-table.h +++ b/deps/v8/src/safepoint-table.h @@ -219,6 +219,9 @@ class SafepointTableBuilder BASE_EMBEDDED { // Record deoptimization index for lazy deoptimization for the last // outstanding safepoints. void RecordLazyDeoptimizationIndex(int index); + void BumpLastLazySafepointIndex() { + last_lazy_safepoint_ = deopt_index_list_.length(); + } // Emit the safepoint table after the body. The number of bits per // entry must be enough to hold all the pointer indexes. diff --git a/deps/v8/src/serialize.h b/deps/v8/src/serialize.h index ee9df39ad8..9229bad406 100644 --- a/deps/v8/src/serialize.h +++ b/deps/v8/src/serialize.h @@ -60,7 +60,7 @@ const int kReferenceTypeShift = kReferenceIdBits; const int kDebugRegisterBits = 4; const int kDebugIdShift = kDebugRegisterBits; -const int kDeoptTableSerializeEntryCount = 8; +const int kDeoptTableSerializeEntryCount = 12; // ExternalReferenceTable is a helper class that defines the relationship // between external references and their encodings. It is used to build diff --git a/deps/v8/src/typedarray.js b/deps/v8/src/typedarray.js index 81c52961c0..4195dd5ea8 100644 --- a/deps/v8/src/typedarray.js +++ b/deps/v8/src/typedarray.js @@ -49,12 +49,20 @@ endmacro macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) { + if (!IS_UNDEFINED(byteOffset)) { + byteOffset = + ToPositiveInteger(byteOffset, "invalid_typed_array_length"); + } + if (!IS_UNDEFINED(length)) { + length = ToPositiveInteger(length, "invalid_typed_array_length"); + } + var bufferByteLength = %ArrayBufferGetByteLength(buffer); var offset; if (IS_UNDEFINED(byteOffset)) { offset = 0; } else { - offset = ToPositiveInteger(byteOffset, "invalid_typed_array_length"); + offset = byteOffset; if (offset % ELEMENT_SIZE !== 0) { throw MakeRangeError("invalid_typed_array_alignment", @@ -75,7 +83,7 @@ macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) newByteLength = bufferByteLength - offset; newLength = newByteLength / ELEMENT_SIZE; } else { - var newLength = ToPositiveInteger(length, "invalid_typed_array_length"); + var newLength = length; newByteLength = newLength * ELEMENT_SIZE; } if ((offset + newByteLength > bufferByteLength) @@ -99,6 +107,7 @@ macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) function NAMEConstructByArrayLike(obj, arrayLike) { var length = arrayLike.length; var l = ToPositiveInteger(length, "invalid_typed_array_length"); + if (l > %MaxSmi()) { throw MakeRangeError("invalid_typed_array_length"); } @@ -148,15 +157,19 @@ function TypedArrayGetLength() { function CreateSubArray(elementSize, constructor) { return function(begin, end) { - var srcLength = %TypedArrayGetLength(this); var beginInt = TO_INTEGER(begin); + if (!IS_UNDEFINED(end)) { + end = TO_INTEGER(end); + } + + var srcLength = %TypedArrayGetLength(this); if (beginInt < 0) { beginInt = MathMax(0, srcLength + beginInt); } else { beginInt = MathMin(srcLength, beginInt); } - var endInt = IS_UNDEFINED(end) ? srcLength : TO_INTEGER(end); + var endInt = IS_UNDEFINED(end) ? srcLength : end; if (endInt < 0) { endInt = MathMax(0, srcLength + endInt); } else { @@ -317,14 +330,23 @@ function DataViewConstructor(buffer, byteOffset, byteLength) { // length = 3 if (!IS_ARRAYBUFFER(buffer)) { throw MakeTypeError('data_view_not_array_buffer', []); } + if (!IS_UNDEFINED(byteOffset)) { + byteOffset = ToPositiveInteger(byteOffset, 'invalid_data_view_offset'); + } + if (!IS_UNDEFINED(byteLength)) { + byteLength = TO_INTEGER(byteLength); + } + var bufferByteLength = %ArrayBufferGetByteLength(buffer); - var offset = IS_UNDEFINED(byteOffset) ? - 0 : ToPositiveInteger(byteOffset, 'invalid_data_view_offset'); + + var offset = IS_UNDEFINED(byteOffset) ? 0 : byteOffset; if (offset > bufferByteLength) { throw MakeRangeError('invalid_data_view_offset'); } - var length = IS_UNDEFINED(byteLength) ? - bufferByteLength - offset : TO_INTEGER(byteLength); + + var length = IS_UNDEFINED(byteLength) + ? bufferByteLength - offset + : byteLength; if (length < 0 || offset + length > bufferByteLength) { throw new MakeRangeError('invalid_data_view_length'); } diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index 4f6ca83e89..9ba044d5a6 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -35,7 +35,7 @@ #define MAJOR_VERSION 3 #define MINOR_VERSION 24 #define BUILD_NUMBER 35 -#define PATCH_LEVEL 17 +#define PATCH_LEVEL 22 // 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 c3b6e845fb..2cb09325fd 100644 --- a/deps/v8/src/x64/lithium-codegen-x64.cc +++ b/deps/v8/src/x64/lithium-codegen-x64.cc @@ -273,6 +273,13 @@ void LCodeGen::GenerateOsrPrologue() { } +void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { + if (!instr->IsLazyBailout() && !instr->IsGap()) { + safepoints_.BumpLastLazySafepointIndex(); + } +} + + bool LCodeGen::GenerateJumpTable() { Label needs_frame; if (jump_table_.length() > 0) { @@ -1870,7 +1877,6 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) { BinaryOpICStub stub(instr->op(), NO_OVERWRITE); CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); - __ nop(); // Signals no inlined code. } @@ -4289,7 +4295,8 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { __ movp(rax, object_reg); } __ Move(rbx, to_map); - TransitionElementsKindStub stub(from_kind, to_kind); + bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; + TransitionElementsKindStub stub(from_kind, to_kind, is_js_array); __ CallStub(&stub); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); diff --git a/deps/v8/src/x64/lithium-codegen-x64.h b/deps/v8/src/x64/lithium-codegen-x64.h index 0f1a9cdb70..431f77b234 100644 --- a/deps/v8/src/x64/lithium-codegen-x64.h +++ b/deps/v8/src/x64/lithium-codegen-x64.h @@ -159,6 +159,7 @@ class LCodeGen: public LCodeGenBase { // Code generation passes. Returns true if code generation should // continue. + void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE; bool GeneratePrologue(); bool GenerateDeferredCode(); bool GenerateJumpTable(); diff --git a/deps/v8/src/x64/lithium-x64.cc b/deps/v8/src/x64/lithium-x64.cc index 511b6b6615..1f2b1e98e0 100644 --- a/deps/v8/src/x64/lithium-x64.cc +++ b/deps/v8/src/x64/lithium-x64.cc @@ -630,15 +630,6 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, instr->MarkAsCall(); instr = AssignPointerMap(instr); - if (hinstr->HasObservableSideEffects()) { - ASSERT(hinstr->next()->IsSimulate()); - HSimulate* sim = HSimulate::cast(hinstr->next()); - ASSERT(instruction_pending_deoptimization_environment_ == NULL); - ASSERT(pending_deoptimization_ast_id_.IsNone()); - instruction_pending_deoptimization_environment_ = instr; - pending_deoptimization_ast_id_ = sim->ast_id(); - } - // If instruction does not have side-effects lazy deoptimization // after the call will try to deoptimize to the point before the call. // Thus we still need to attach environment to this call even if @@ -916,6 +907,26 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) { instr = AssignEnvironment(instr); } chunk_->AddInstruction(instr, current_block_); + + if (instr->IsCall()) { + HValue* hydrogen_value_for_lazy_bailout = current; + LInstruction* instruction_needing_environment = NULL; + if (current->HasObservableSideEffects()) { + HSimulate* sim = HSimulate::cast(current->next()); + instruction_needing_environment = instr; + sim->ReplayEnvironment(current_block_->last_environment()); + hydrogen_value_for_lazy_bailout = sim; + } + LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout()); + bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); + chunk_->AddInstruction(bailout, current_block_); + if (instruction_needing_environment != NULL) { + // Store the lazy deopt environment with the instruction if needed. + // Right now it is only used for LInstanceOfKnownGlobal. + instruction_needing_environment-> + SetDeferredLazyDeoptimizationEnvironment(bailout->environment()); + } + } } current_instruction_ = old_current; } @@ -2334,21 +2345,6 @@ LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { instr->ReplayEnvironment(current_block_->last_environment()); - - // If there is an instruction pending deoptimization environment create a - // lazy bailout instruction to capture the environment. - if (pending_deoptimization_ast_id_ == instr->ast_id()) { - LLazyBailout* lazy_bailout = new(zone()) LLazyBailout; - LInstruction* result = AssignEnvironment(lazy_bailout); - // Store the lazy deopt environment with the instruction if needed. Right - // now it is only used for LInstanceOfKnownGlobal. - instruction_pending_deoptimization_environment_-> - SetDeferredLazyDeoptimizationEnvironment(result->environment()); - instruction_pending_deoptimization_environment_ = NULL; - pending_deoptimization_ast_id_ = BailoutId::None(); - return result; - } - return NULL; } diff --git a/deps/v8/src/x64/lithium-x64.h b/deps/v8/src/x64/lithium-x64.h index 9785fcc838..36b2744401 100644 --- a/deps/v8/src/x64/lithium-x64.h +++ b/deps/v8/src/x64/lithium-x64.h @@ -2510,9 +2510,7 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { current_instruction_(NULL), current_block_(NULL), next_block_(NULL), - allocator_(allocator), - instruction_pending_deoptimization_environment_(NULL), - pending_deoptimization_ast_id_(BailoutId::None()) { } + allocator_(allocator) { } // Build the sequence for the graph. LPlatformChunk* Build(); @@ -2648,8 +2646,6 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { HBasicBlock* current_block_; HBasicBlock* next_block_; LAllocator* allocator_; - LInstruction* instruction_pending_deoptimization_environment_; - BailoutId pending_deoptimization_ast_id_; DISALLOW_COPY_AND_ASSIGN(LChunkBuilder); }; diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 447cd261ce..e58612705d 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -21965,3 +21965,48 @@ TEST(TestFunctionCallOptimization) { checker.Run(true, false); checker.Run(false, false); } + + +TEST(Regress354123) { + LocalContext current; + v8::Isolate* isolate = current->GetIsolate(); + v8::HandleScope scope(isolate); + + v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); + templ->SetAccessCheckCallbacks(NamedAccessCounter, IndexedAccessCounter); + current->Global()->Set(v8_str("friend"), templ->NewInstance()); + + // Test access using __proto__ from the prototype chain. + named_access_count = 0; + CompileRun("friend.__proto__ = {};"); + CHECK_EQ(2, named_access_count); + CompileRun("friend.__proto__;"); + CHECK_EQ(4, named_access_count); + + // Test access using __proto__ as a hijacked function (A). + named_access_count = 0; + CompileRun("var p = Object.prototype;" + "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;" + "f.call(friend, {});"); + CHECK_EQ(1, named_access_count); + CompileRun("var p = Object.prototype;" + "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;" + "f.call(friend);"); + CHECK_EQ(2, named_access_count); + + // Test access using __proto__ as a hijacked function (B). + named_access_count = 0; + CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');" + "f.call(friend, {});"); + CHECK_EQ(1, named_access_count); + CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');" + "f.call(friend);"); + CHECK_EQ(2, named_access_count); + + // Test access using Object.setPrototypeOf reflective method. + named_access_count = 0; + CompileRun("Object.setPrototypeOf(friend, {});"); + CHECK_EQ(1, named_access_count); + CompileRun("Object.getPrototypeOf(friend);"); + CHECK_EQ(2, named_access_count); +} diff --git a/deps/v8/test/mjsunit/regress/regress-350863.js b/deps/v8/test/mjsunit/regress/regress-350863.js new file mode 100644 index 0000000000..616792b82c --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-350863.js @@ -0,0 +1,45 @@ +// Copyright 2014 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 + +var __v_7 = { }; +function __f_8(base, condition) { + __v_7[base + 3] = 0; + __v_7[base + 4] = 0; + if (condition) { + __v_7[base + 0] = 0; + __v_7[base + 5] = 0; + } else { + __v_7[base + 0] = 0; + __v_7[base + 18] = 0; + } +} +__f_8(1, true); +__f_8(1, false); +%OptimizeFunctionOnNextCall(__f_8); +__f_8(5, false); diff --git a/deps/v8/test/mjsunit/regress/regress-352982.js b/deps/v8/test/mjsunit/regress/regress-352982.js new file mode 100644 index 0000000000..5d3ce1c67d --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-352982.js @@ -0,0 +1,51 @@ +// Copyright 2014 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 --expose-gc + +function __f_4(i1) { + return __v_3[i1] * __v_3[0]; +} +function __f_3(i1) { + __f_4(i1); + __f_4(i1 + 16); + __f_4(i1 + 32); + %OptimizeFunctionOnNextCall(__f_4); + var x = __f_4(i1 + 993); + return x; +} +function __f_5() { + __v_3[0] = +__v_3[0]; + gc(); + __f_3(0) | 0; + __v_3 = /\u23a1|x/; + return 0; +} +var __v_3 = new Float32Array(1000); +__f_5(); +__f_5(); +__f_5(); diff --git a/deps/v8/test/mjsunit/regress/regress-353004.js b/deps/v8/test/mjsunit/regress/regress-353004.js new file mode 100644 index 0000000000..658fd6dbeb --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-353004.js @@ -0,0 +1,74 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var buffer1 = new ArrayBuffer(100 * 1024); + +var array1 = new Uint8Array(buffer1, {valueOf : function() { + %ArrayBufferNeuter(buffer1); + return 0; +}}); + +assertEquals(0, array1.length); + +var buffer2 = new ArrayBuffer(100 * 1024); + +assertThrows(function() { + var array2 = new Uint8Array(buffer2, 0, {valueOf : function() { + %ArrayBufferNeuter(buffer2); + return 100 * 1024; + }}); +}, RangeError); + + +var buffer3 = new ArrayBuffer(100 * 1024 * 1024); +var dataView1 = new DataView(buffer3, {valueOf : function() { + %ArrayBufferNeuter(buffer3); + return 0; +}}); + +assertEquals(0, dataView1.byteLength); + +var buffer4 = new ArrayBuffer(100 * 1024); +assertThrows(function() { + var dataView2 = new DataView(buffer4, 0, {valueOf : function() { + %ArrayBufferNeuter(buffer4); + return 100 * 1024 * 1024; + }}); +}, RangeError); + + +var buffer5 = new ArrayBuffer(100 * 1024); +var buffer6 = buffer5.slice({valueOf : function() { + %ArrayBufferNeuter(buffer5); + return 0; +}}, 100 * 1024 * 1024); +assertEquals(0, buffer6.byteLength); + + +var buffer7 = new ArrayBuffer(100 * 1024 * 1024); +var buffer8 = buffer7.slice(0, {valueOf : function() { + %ArrayBufferNeuter(buffer7); + return 100 * 1024 * 1024; +}}); +assertEquals(0, buffer8.byteLength); + +var buffer9 = new ArrayBuffer(1024); +var array9 = new Uint8Array(buffer9); +var array10 = array9.subarray({valueOf : function() { + %ArrayBufferNeuter(buffer9); + return 0; + }}, 1024); +assertEquals(0, array9.length); +assertEquals(0, array10.length); + +var buffer11 = new ArrayBuffer(1024); +var array11 = new Uint8Array(buffer11); +var array12 = array11.subarray(0, {valueOf : function() { + %ArrayBufferNeuter(buffer11); + return 1024; + }}); +assertEquals(0, array11.length); +assertEquals(0, array12.length); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-352929.js b/deps/v8/test/mjsunit/regress/regress-crbug-352929.js new file mode 100644 index 0000000000..a5872c1258 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-352929.js @@ -0,0 +1,33 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var dummy = new Int32Array(100); +array = new Int32Array(100); +var dummy2 = new Int32Array(100); + +array[-17] = 0; +function fun(base,cond) { + array[base - 1] = 1; + array[base - 2] = 2; + if (cond) { + array[base - 4] = 3; + array[base - 5] = 4; + } else { + array[base - 6] = 5; + array[base - 100] = 777; + } +} +fun(5,true); +fun(7,false); +%OptimizeFunctionOnNextCall(fun); +fun(7,false); + +for (var i = 0; i < dummy.length; i++) { + assertEquals(0, dummy[i]); +} +for (var i = 0; i < dummy2.length; i++) { + assertEquals(0, dummy2[i]); +} |