diff options
author | isaacs <i@izs.me> | 2012-03-12 21:46:36 -0700 |
---|---|---|
committer | isaacs <i@izs.me> | 2012-03-12 21:46:36 -0700 |
commit | e4fc2cbfd354d8ad74c465e508531d92de2b4d52 (patch) | |
tree | ce1e20dddced61d5b56750743ddb7304846f537a /deps/v8/src/arm | |
parent | bcb0cc0b184c61313541002e504948ed21f59dad (diff) | |
download | node-new-e4fc2cbfd354d8ad74c465e508531d92de2b4d52.tar.gz |
Upgrade v8 to 3.9.17
Diffstat (limited to 'deps/v8/src/arm')
-rw-r--r-- | deps/v8/src/arm/assembler-arm.cc | 10 | ||||
-rw-r--r-- | deps/v8/src/arm/builtins-arm.cc | 7 | ||||
-rw-r--r-- | deps/v8/src/arm/code-stubs-arm.cc | 78 | ||||
-rw-r--r-- | deps/v8/src/arm/codegen-arm.cc | 13 | ||||
-rw-r--r-- | deps/v8/src/arm/deoptimizer-arm.cc | 126 | ||||
-rw-r--r-- | deps/v8/src/arm/full-codegen-arm.cc | 69 | ||||
-rw-r--r-- | deps/v8/src/arm/ic-arm.cc | 8 | ||||
-rw-r--r-- | deps/v8/src/arm/lithium-arm.cc | 443 | ||||
-rw-r--r-- | deps/v8/src/arm/lithium-arm.h | 55 | ||||
-rw-r--r-- | deps/v8/src/arm/lithium-codegen-arm.cc | 192 | ||||
-rw-r--r-- | deps/v8/src/arm/lithium-codegen-arm.h | 2 | ||||
-rw-r--r-- | deps/v8/src/arm/regexp-macro-assembler-arm.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/arm/stub-cache-arm.cc | 100 |
13 files changed, 804 insertions, 301 deletions
diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc index 25922361a2..ff15221119 100644 --- a/deps/v8/src/arm/assembler-arm.cc +++ b/deps/v8/src/arm/assembler-arm.cc @@ -66,11 +66,13 @@ static uint64_t CpuFeaturesImpliedByCompiler() { #ifdef __arm__ // If the compiler is allowed to use VFP then we can use VFP too in our code - // generation even when generating snapshots. This won't work for cross - // compilation. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6. -#if defined(__VFP_FP__) && !defined(__SOFTFP__) + // generation even when generating snapshots. ARMv7 and hardware floating + // point support implies VFPv3, see ARM DDI 0406B, page A1-6. +#if defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) \ + && !defined(__SOFTFP__) answer |= 1u << VFP3 | 1u << ARMv7; -#endif // defined(__VFP_FP__) && !defined(__SOFTFP__) +#endif // defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) + // && !defined(__SOFTFP__) #endif // def __arm__ return answer; diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc index 993addca9e..c99e778a7f 100644 --- a/deps/v8/src/arm/builtins-arm.cc +++ b/deps/v8/src/arm/builtins-arm.cc @@ -978,6 +978,11 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, NullCallWrapper(), CALL_AS_METHOD); } + // Store offset of return address for deoptimizer. + if (!is_api_function && !count_constructions) { + masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); + } + // Restore context from the frame. // r0: result // sp[0]: receiver @@ -1740,7 +1745,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { __ bind(&invoke); __ Call(r3); + // Store offset of return address for deoptimizer. masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); + // Exit frame and return. LeaveArgumentsAdaptorFrame(masm); __ Jump(lr); diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc index 62e6c80271..250f020a62 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/deps/v8/src/arm/code-stubs-arm.cc @@ -5930,8 +5930,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { __ bind(&sliced_string); // Sliced string. Fetch parent and correct start index by offset. - __ ldr(r4, FieldMemOperand(r0, SlicedString::kOffsetOffset)); __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); + __ ldr(r4, FieldMemOperand(r0, SlicedString::kOffsetOffset)); __ add(r3, r3, Operand(r4, ASR, 1)); // Add offset to index. // Update instance type. __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); @@ -5969,8 +5969,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { __ AllocateTwoByteSlicedString(r0, r2, r6, r7, &runtime); __ bind(&set_slice_header); __ mov(r3, Operand(r3, LSL, 1)); - __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset)); __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); + __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset)); __ jmp(&return_r0); __ bind(©_routine); @@ -6560,15 +6560,15 @@ void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { ASSERT(state_ == CompareIC::HEAP_NUMBERS); Label generic_stub; - Label unordered; + Label unordered, maybe_undefined1, maybe_undefined2; Label miss; __ and_(r2, r1, Operand(r0)); __ JumpIfSmi(r2, &generic_stub); __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE); - __ b(ne, &miss); + __ b(ne, &maybe_undefined1); __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); - __ b(ne, &miss); + __ b(ne, &maybe_undefined2); // Inlining the double comparison and falling back to the general compare // stub if NaN is involved or VFP3 is unsupported. @@ -6592,14 +6592,28 @@ void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { __ mov(r0, Operand(LESS), LeaveCC, lt); __ mov(r0, Operand(GREATER), LeaveCC, gt); __ Ret(); - - __ bind(&unordered); } + __ bind(&unordered); CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, r1, r0); __ bind(&generic_stub); __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); + __ bind(&maybe_undefined1); + if (Token::IsOrderedRelationalCompareOp(op_)) { + __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); + __ b(ne, &miss); + __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); + __ b(ne, &maybe_undefined2); + __ jmp(&unordered); + } + + __ bind(&maybe_undefined2); + if (Token::IsOrderedRelationalCompareOp(op_)) { + __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); + __ b(eq, &unordered); + } + __ bind(&miss); GenerateMiss(masm); } @@ -6647,6 +6661,8 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) { ASSERT(state_ == CompareIC::STRINGS); Label miss; + bool equality = Token::IsEqualityOp(op_); + // Registers containing left and right operands respectively. Register left = r1; Register right = r0; @@ -6680,28 +6696,39 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) { // Check that both strings are symbols. If they are, we're done // because we already know they are not identical. - ASSERT(GetCondition() == eq); - STATIC_ASSERT(kSymbolTag != 0); - __ and_(tmp3, tmp1, Operand(tmp2)); - __ tst(tmp3, Operand(kIsSymbolMask)); - // Make sure r0 is non-zero. At this point input operands are - // guaranteed to be non-zero. - ASSERT(right.is(r0)); - __ Ret(ne); + if (equality) { + ASSERT(GetCondition() == eq); + STATIC_ASSERT(kSymbolTag != 0); + __ and_(tmp3, tmp1, Operand(tmp2)); + __ tst(tmp3, Operand(kIsSymbolMask)); + // Make sure r0 is non-zero. At this point input operands are + // guaranteed to be non-zero. + ASSERT(right.is(r0)); + __ Ret(ne); + } // Check that both strings are sequential ASCII. Label runtime; - __ JumpIfBothInstanceTypesAreNotSequentialAscii(tmp1, tmp2, tmp3, tmp4, - &runtime); + __ JumpIfBothInstanceTypesAreNotSequentialAscii( + tmp1, tmp2, tmp3, tmp4, &runtime); // Compare flat ASCII strings. Returns when done. - StringCompareStub::GenerateFlatAsciiStringEquals( - masm, left, right, tmp1, tmp2, tmp3); + if (equality) { + StringCompareStub::GenerateFlatAsciiStringEquals( + masm, left, right, tmp1, tmp2, tmp3); + } else { + StringCompareStub::GenerateCompareFlatAsciiStrings( + masm, left, right, tmp1, tmp2, tmp3, tmp4); + } // Handle more complex cases in runtime. __ bind(&runtime); __ Push(left, right); - __ TailCallRuntime(Runtime::kStringEquals, 2, 1); + if (equality) { + __ TailCallRuntime(Runtime::kStringEquals, 2, 1); + } else { + __ TailCallRuntime(Runtime::kStringCompare, 2, 1); + } __ bind(&miss); GenerateMiss(masm); @@ -6812,7 +6839,7 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, // not equal to the name and kProbes-th slot is not used (its name is the // undefined value), it guarantees the hash table doesn't contain the // property. It's true even if some slots represent deleted properties - // (their names are the null value). + // (their names are the hole value). for (int i = 0; i < kInlinedProbes; i++) { // scratch0 points to properties hash. // Compute the masked index: (hash + i + i * i) & mask. @@ -6840,10 +6867,17 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ b(eq, done); if (i != kInlinedProbes - 1) { + // Load the hole ready for use below: + __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); + // Stop if found the property. __ cmp(entity_name, Operand(Handle<String>(name))); __ b(eq, miss); + Label the_hole; + __ cmp(entity_name, tmp); + __ b(eq, &the_hole); + // Check if the entry name is not a symbol. __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); __ ldrb(entity_name, @@ -6851,6 +6885,8 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, __ tst(entity_name, Operand(kIsSymbolMask)); __ b(eq, miss); + __ bind(&the_hole); + // Restore the properties. __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index 506f9b2d5d..6e18277783 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/deps/v8/src/arm/codegen-arm.cc @@ -37,6 +37,19 @@ namespace internal { #define __ ACCESS_MASM(masm) +TranscendentalFunction CreateTranscendentalFunction( + TranscendentalCache::Type type) { + switch (type) { + case TranscendentalCache::SIN: return &sin; + case TranscendentalCache::COS: return &cos; + case TranscendentalCache::TAN: return &tan; + case TranscendentalCache::LOG: return &log; + default: UNIMPLEMENTED(); + } + return NULL; +} + + // ------------------------------------------------------------------------- // Platform-specific RuntimeCallHelper functions. diff --git a/deps/v8/src/arm/deoptimizer-arm.cc b/deps/v8/src/arm/deoptimizer-arm.cc index 76d89541c5..d9a4d4b0f4 100644 --- a/deps/v8/src/arm/deoptimizer-arm.cc +++ b/deps/v8/src/arm/deoptimizer-arm.cc @@ -351,7 +351,6 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, } unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; - unsigned input_frame_size = input_->GetFrameSize(); unsigned output_frame_size = height_in_bytes + fixed_frame_size; // Allocate and store the output frame description. @@ -373,16 +372,13 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, // Compute the incoming parameter translation. int parameter_count = height; unsigned output_offset = output_frame_size; - unsigned input_offset = input_frame_size; for (int i = 0; i < parameter_count; ++i) { output_offset -= kPointerSize; DoTranslateCommand(iterator, frame_index, output_offset); } - input_offset -= (parameter_count * kPointerSize); // Read caller's PC from the previous frame. output_offset -= kPointerSize; - input_offset -= kPointerSize; intptr_t callers_pc = output_[frame_index - 1]->GetPc(); output_frame->SetFrameSlot(output_offset, callers_pc); if (FLAG_trace_deopt) { @@ -392,7 +388,6 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, // Read caller's FP from the previous frame, and set this frame's FP. output_offset -= kPointerSize; - input_offset -= kPointerSize; intptr_t value = output_[frame_index - 1]->GetFp(); output_frame->SetFrameSlot(output_offset, value); intptr_t fp_value = top_address + output_offset; @@ -404,7 +399,6 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, // A marker value is used in place of the context. output_offset -= kPointerSize; - input_offset -= kPointerSize; intptr_t context = reinterpret_cast<intptr_t>( Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); output_frame->SetFrameSlot(output_offset, context); @@ -415,7 +409,6 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME. output_offset -= kPointerSize; - input_offset -= kPointerSize; value = reinterpret_cast<intptr_t>(function); output_frame->SetFrameSlot(output_offset, value); if (FLAG_trace_deopt) { @@ -425,7 +418,6 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, // Number of incoming arguments. output_offset -= kPointerSize; - input_offset -= kPointerSize; value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1)); output_frame->SetFrameSlot(output_offset, value); if (FLAG_trace_deopt) { @@ -445,6 +437,119 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, } +void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, + int frame_index) { + JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); + unsigned height = iterator->Next(); + unsigned height_in_bytes = height * kPointerSize; + if (FLAG_trace_deopt) { + PrintF(" translating construct stub => height=%d\n", height_in_bytes); + } + + unsigned fixed_frame_size = 7 * kPointerSize; + unsigned output_frame_size = height_in_bytes + fixed_frame_size; + + // Allocate and store the output frame description. + FrameDescription* output_frame = + new(output_frame_size) FrameDescription(output_frame_size, function); + output_frame->SetFrameType(StackFrame::CONSTRUCT); + + // Construct stub can not be topmost or bottommost. + ASSERT(frame_index > 0 && frame_index < output_count_ - 1); + ASSERT(output_[frame_index] == NULL); + output_[frame_index] = output_frame; + + // The top address of the frame is computed from the previous + // frame's top and this frame's size. + uint32_t top_address; + top_address = output_[frame_index - 1]->GetTop() - output_frame_size; + output_frame->SetTop(top_address); + + // Compute the incoming parameter translation. + int parameter_count = height; + unsigned output_offset = output_frame_size; + for (int i = 0; i < parameter_count; ++i) { + output_offset -= kPointerSize; + DoTranslateCommand(iterator, frame_index, output_offset); + } + + // Read caller's PC from the previous frame. + output_offset -= kPointerSize; + intptr_t callers_pc = output_[frame_index - 1]->GetPc(); + output_frame->SetFrameSlot(output_offset, callers_pc); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n", + top_address + output_offset, output_offset, callers_pc); + } + + // Read caller's FP from the previous frame, and set this frame's FP. + output_offset -= kPointerSize; + intptr_t value = output_[frame_index - 1]->GetFp(); + output_frame->SetFrameSlot(output_offset, value); + intptr_t fp_value = top_address + output_offset; + output_frame->SetFp(fp_value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", + fp_value, output_offset, value); + } + + // The context can be gotten from the previous frame. + output_offset -= kPointerSize; + value = output_[frame_index - 1]->GetContext(); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context\n", + top_address + output_offset, output_offset, value); + } + + // A marker value is used in place of the function. + output_offset -= kPointerSize; + value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT)); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n", + top_address + output_offset, output_offset, value); + } + + // Number of incoming arguments. + output_offset -= kPointerSize; + value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1)); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n", + top_address + output_offset, output_offset, value, height - 1); + } + + // Constructor function being invoked by the stub. + output_offset -= kPointerSize; + value = reinterpret_cast<intptr_t>(function); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; constructor function\n", + top_address + output_offset, output_offset, value); + } + + // The newly allocated object was passed as receiver in the artificial + // constructor stub environment created by HEnvironment::CopyForInlining(). + output_offset -= kPointerSize; + value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n", + top_address + output_offset, output_offset, value); + } + + ASSERT(0 == output_offset); + + Builtins* builtins = isolate_->builtins(); + Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); + uint32_t pc = reinterpret_cast<uint32_t>( + construct_stub->instruction_start() + + isolate_->heap()->construct_stub_deopt_pc_offset()->value()); + output_frame->SetPc(pc); +} + + // This code is very similar to ia32 code, but relies on register names (fp, sp) // and how the frame is laid out. void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, @@ -557,9 +662,8 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, value = reinterpret_cast<intptr_t>(function->context()); } output_frame->SetFrameSlot(output_offset, value); - if (is_topmost) { - output_frame->SetRegister(cp.code(), value); - } + output_frame->SetContext(value); + if (is_topmost) output_frame->SetRegister(cp.code(), value); if (FLAG_trace_deopt) { PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context\n", top_address + output_offset, output_offset, value); diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index 51e9208332..77f4e4414d 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -1004,6 +1004,16 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // We got a fixed array in register r0. Iterate through that. Label non_proxy; __ bind(&fixed_array); + + Handle<JSGlobalPropertyCell> cell = + isolate()->factory()->NewJSGlobalPropertyCell( + Handle<Object>( + Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker))); + RecordTypeFeedbackCell(stmt->PrepareId(), cell); + __ LoadHeapObject(r1, cell); + __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); + __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset)); + __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); @@ -1488,11 +1498,15 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ ldr(r0, MemOperand(sp)); __ push(r0); VisitForStackValue(key); - __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? - Smi::FromInt(1) : - Smi::FromInt(0))); - __ push(r1); - VisitForStackValue(value); + if (property->kind() == ObjectLiteral::Property::GETTER) { + VisitForStackValue(value); + __ LoadRoot(r1, Heap::kNullValueRootIndex); + __ push(r1); + } else { + __ LoadRoot(r1, Heap::kNullValueRootIndex); + __ push(r1); + VisitForStackValue(value); + } __ mov(r0, Operand(Smi::FromInt(NONE))); __ push(r0); __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5); @@ -2382,6 +2396,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { CallConstructStub stub(flags); __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); + PrepareForBailoutForId(expr->ReturnId(), TOS_REG); context()->Plug(r0); } @@ -2932,6 +2947,50 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { } +void FullCodeGenerator::EmitDateField(CallRuntime* expr) { + ZoneList<Expression*>* args = expr->arguments(); + ASSERT(args->length() == 2); + ASSERT_NE(NULL, args->at(1)->AsLiteral()); + Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle())); + + VisitForAccumulatorValue(args->at(0)); // Load the object. + + Label runtime, done; + Register object = r0; + Register result = r0; + Register scratch0 = r9; + Register scratch1 = r1; + +#ifdef DEBUG + __ AbortIfSmi(object); + __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE); + __ Assert(eq, "Trying to get date field from non-date."); +#endif + + if (index->value() == 0) { + __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); + } else { + if (index->value() < JSDate::kFirstUncachedField) { + ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); + __ mov(scratch1, Operand(stamp)); + __ ldr(scratch1, MemOperand(scratch1)); + __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset)); + __ cmp(scratch1, scratch0); + __ b(ne, &runtime); + __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset + + kPointerSize * index->value())); + __ jmp(&done); + } + __ bind(&runtime); + __ PrepareCallCFunction(2, scratch1); + __ mov(r1, Operand(index)); + __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); + __ bind(&done); + } + context()->Plug(r0); +} + + void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { // Load the arguments on the stack and call the runtime function. ZoneList<Expression*>* args = expr->arguments(); diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc index 14daadaea9..e84365789b 100644 --- a/deps/v8/src/arm/ic-arm.cc +++ b/deps/v8/src/arm/ic-arm.cc @@ -399,7 +399,7 @@ void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, NORMAL, argc); Isolate::Current()->stub_cache()->GenerateProbe( - masm, flags, r1, r2, r3, r4, r5); + masm, flags, r1, r2, r3, r4, r5, r6); // If the stub cache probing failed, the receiver might be a value. // For value objects, we use the map of the prototype objects for @@ -438,7 +438,7 @@ void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, // Probe the stub cache for the value object. __ bind(&probe); Isolate::Current()->stub_cache()->GenerateProbe( - masm, flags, r1, r2, r3, r4, r5); + masm, flags, r1, r2, r3, r4, r5, r6); __ bind(&miss); } @@ -706,7 +706,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC); Isolate::Current()->stub_cache()->GenerateProbe( - masm, flags, r0, r2, r3, r4, r5); + masm, flags, r0, r2, r3, r4, r5, r6); // Cache miss: Jump to runtime. GenerateMiss(masm); @@ -1516,7 +1516,7 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm, Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode); Isolate::Current()->stub_cache()->GenerateProbe( - masm, flags, r1, r2, r3, r4, r5); + masm, flags, r1, r2, r3, r4, r5, r6); // Cache miss: Jump to runtime. GenerateMiss(masm); diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index a934aacd36..36421d9bd3 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -440,7 +440,7 @@ LOperand* LChunk::GetNextSpillSlot(bool is_double) { void LChunk::MarkEmptyBlocks() { - HPhase phase("Mark empty blocks", this); + HPhase phase("L_Mark empty blocks", this); for (int i = 0; i < graph()->blocks()->length(); ++i) { HBasicBlock* block = graph()->blocks()->at(i); int first = block->first_instruction_index(); @@ -476,7 +476,7 @@ void LChunk::MarkEmptyBlocks() { void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { - LInstructionGap* gap = new LInstructionGap(block); + LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block); int index = -1; if (instr->IsControl()) { instructions_.Add(gap); @@ -551,8 +551,8 @@ Representation LChunk::LookupLiteralRepresentation( LChunk* LChunkBuilder::Build() { ASSERT(is_unused()); - chunk_ = new LChunk(info(), graph()); - HPhase phase("Building chunk", chunk_); + chunk_ = new(zone()) LChunk(info(), graph()); + HPhase phase("L_Building chunk", chunk_); status_ = BUILDING; const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); for (int i = 0; i < blocks->length(); i++) { @@ -582,14 +582,14 @@ void LChunkBuilder::Abort(const char* format, ...) { LUnallocated* LChunkBuilder::ToUnallocated(Register reg) { - return new LUnallocated(LUnallocated::FIXED_REGISTER, - Register::ToAllocationIndex(reg)); + return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER, + Register::ToAllocationIndex(reg)); } LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) { - return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, - DoubleRegister::ToAllocationIndex(reg)); + return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, + DoubleRegister::ToAllocationIndex(reg)); } @@ -604,30 +604,30 @@ LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) { LOperand* LChunkBuilder::UseRegister(HValue* value) { - return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); + return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); } LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) { return Use(value, - new LUnallocated(LUnallocated::MUST_HAVE_REGISTER, - LUnallocated::USED_AT_START)); + new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER, + LUnallocated::USED_AT_START)); } LOperand* LChunkBuilder::UseTempRegister(HValue* value) { - return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER)); + return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER)); } LOperand* LChunkBuilder::Use(HValue* value) { - return Use(value, new LUnallocated(LUnallocated::NONE)); + return Use(value, new(zone()) LUnallocated(LUnallocated::NONE)); } LOperand* LChunkBuilder::UseAtStart(HValue* value) { - return Use(value, new LUnallocated(LUnallocated::NONE, - LUnallocated::USED_AT_START)); + return Use(value, new(zone()) LUnallocated(LUnallocated::NONE, + LUnallocated::USED_AT_START)); } @@ -662,7 +662,7 @@ LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { LOperand* LChunkBuilder::UseAny(HValue* value) { return value->IsConstant() ? chunk_->DefineConstantOperand(HConstant::cast(value)) - : Use(value, new LUnallocated(LUnallocated::ANY)); + : Use(value, new(zone()) LUnallocated(LUnallocated::ANY)); } @@ -688,21 +688,24 @@ LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr, template<int I, int T> LInstruction* LChunkBuilder::DefineAsRegister( LTemplateInstruction<1, I, T>* instr) { - return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); + return Define(instr, + new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); } template<int I, int T> LInstruction* LChunkBuilder::DefineAsSpilled( LTemplateInstruction<1, I, T>* instr, int index) { - return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index)); + return Define(instr, + new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index)); } template<int I, int T> LInstruction* LChunkBuilder::DefineSameAsFirst( LTemplateInstruction<1, I, T>* instr) { - return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); + return Define(instr, + new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); } @@ -784,13 +787,14 @@ LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { ASSERT(!instr->HasPointerMap()); - instr->set_pointer_map(new LPointerMap(position_)); + instr->set_pointer_map(new(zone()) LPointerMap(position_)); return instr; } LUnallocated* LChunkBuilder::TempRegister() { - LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER); + LUnallocated* operand = + new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER); operand->set_virtual_register(allocator_->GetVirtualRegister()); if (!allocator_->AllocationOk()) Abort("Not enough virtual registers."); return operand; @@ -812,17 +816,17 @@ LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) { LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { - return new LLabel(instr->block()); + return new(zone()) LLabel(instr->block()); } LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { - return AssignEnvironment(new LDeoptimize); + return AssignEnvironment(new(zone()) LDeoptimize); } LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { - return AssignEnvironment(new LDeoptimize); + return AssignEnvironment(new(zone()) LDeoptimize); } @@ -834,7 +838,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, LOperand* left = UseFixed(instr->left(), r1); LOperand* right = UseFixed(instr->right(), r0); - LArithmeticT* result = new LArithmeticT(op, left, right); + LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -868,7 +872,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, } LInstruction* result = - DefineAsRegister(new LShiftI(op, left, right, does_deopt)); + DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); return does_deopt ? AssignEnvironment(result) : result; } @@ -881,7 +885,7 @@ LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, ASSERT(op != Token::MOD); LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseRegisterAtStart(instr->right()); - LArithmeticD* result = new LArithmeticD(op, left, right); + LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); return DefineAsRegister(result); } @@ -899,7 +903,8 @@ LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, ASSERT(right->representation().IsTagged()); LOperand* left_operand = UseFixed(left, r1); LOperand* right_operand = UseFixed(right, r0); - LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand); + LArithmeticT* result = + new(zone()) LArithmeticT(op, left_operand, right_operand); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -995,15 +1000,17 @@ LEnvironment* LChunkBuilder::CreateEnvironment( LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator); int ast_id = hydrogen_env->ast_id(); - ASSERT(ast_id != AstNode::kNoNumber || hydrogen_env->is_arguments_adaptor()); + ASSERT(ast_id != AstNode::kNoNumber || + hydrogen_env->frame_type() != JS_FUNCTION); int value_count = hydrogen_env->length(); - LEnvironment* result = new LEnvironment(hydrogen_env->closure(), - hydrogen_env->is_arguments_adaptor(), - ast_id, - hydrogen_env->parameter_count(), - argument_count_, - value_count, - outer); + LEnvironment* result = new(zone()) LEnvironment( + hydrogen_env->closure(), + hydrogen_env->frame_type(), + ast_id, + hydrogen_env->parameter_count(), + argument_count_, + value_count, + outer); int argument_index = *argument_index_accumulator; for (int i = 0; i < value_count; ++i) { if (hydrogen_env->is_special_index(i)) continue; @@ -1013,14 +1020,14 @@ LEnvironment* LChunkBuilder::CreateEnvironment( if (value->IsArgumentsObject()) { op = NULL; } else if (value->IsPushArgument()) { - op = new LArgument(argument_index++); + op = new(zone()) LArgument(argument_index++); } else { op = UseAny(value); } result->AddValue(op, value->representation()); } - if (!hydrogen_env->is_arguments_adaptor()) { + if (hydrogen_env->frame_type() == JS_FUNCTION) { *argument_index_accumulator = argument_index; } @@ -1029,7 +1036,7 @@ LEnvironment* LChunkBuilder::CreateEnvironment( LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { - return new LGoto(instr->FirstSuccessor()->block_id()); + return new(zone()) LGoto(instr->FirstSuccessor()->block_id()); } @@ -1039,10 +1046,10 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { HBasicBlock* successor = HConstant::cast(value)->ToBoolean() ? instr->FirstSuccessor() : instr->SecondSuccessor(); - return new LGoto(successor->block_id()); + return new(zone()) LGoto(successor->block_id()); } - LBranch* result = new LBranch(UseRegister(value)); + LBranch* result = new(zone()) LBranch(UseRegister(value)); // Tagged values that are not known smis or booleans require a // deoptimization environment. Representation rep = value->representation(); @@ -1059,23 +1066,24 @@ LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { ASSERT(instr->value()->representation().IsTagged()); LOperand* value = UseRegisterAtStart(instr->value()); LOperand* temp = TempRegister(); - return new LCmpMapAndBranch(value, temp); + return new(zone()) LCmpMapAndBranch(value, temp); } -LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { - return DefineAsRegister(new LArgumentsLength(UseRegister(length->value()))); +LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) { + LOperand* value = UseRegister(instr->value()); + return DefineAsRegister(new(zone()) LArgumentsLength(value)); } LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { - return DefineAsRegister(new LArgumentsElements); + return DefineAsRegister(new(zone()) LArgumentsElements); } LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { LInstanceOf* result = - new LInstanceOf(UseFixed(instr->left(), r0), + new(zone()) LInstanceOf(UseFixed(instr->left(), r0), UseFixed(instr->right(), r1)); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -1084,7 +1092,8 @@ LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( HInstanceOfKnownGlobal* instr) { LInstanceOfKnownGlobal* result = - new LInstanceOfKnownGlobal(UseFixed(instr->left(), r0), FixedTemp(r4)); + new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), r0), + FixedTemp(r4)); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -1094,7 +1103,7 @@ LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { LOperand* receiver = UseFixed(instr->receiver(), r0); LOperand* length = UseFixed(instr->length(), r2); LOperand* elements = UseFixed(instr->elements(), r3); - LApplyArguments* result = new LApplyArguments(function, + LApplyArguments* result = new(zone()) LApplyArguments(function, receiver, length, elements); @@ -1105,73 +1114,75 @@ LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { ++argument_count_; LOperand* argument = Use(instr->argument()); - return new LPushArgument(argument); + return new(zone()) LPushArgument(argument); } LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) { - return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction); + return instr->HasNoUses() + ? NULL + : DefineAsRegister(new(zone()) LThisFunction); } LInstruction* LChunkBuilder::DoContext(HContext* instr) { - return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext); + return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext); } LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { LOperand* context = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LOuterContext(context)); + return DefineAsRegister(new(zone()) LOuterContext(context)); } LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { - return MarkAsCall(new LDeclareGlobals, instr); + return MarkAsCall(new(zone()) LDeclareGlobals, instr); } LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { LOperand* context = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LGlobalObject(context)); + return DefineAsRegister(new(zone()) LGlobalObject(context)); } LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { LOperand* global_object = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LGlobalReceiver(global_object)); + return DefineAsRegister(new(zone()) LGlobalReceiver(global_object)); } LInstruction* LChunkBuilder::DoCallConstantFunction( HCallConstantFunction* instr) { argument_count_ -= instr->argument_count(); - return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, r0), instr); } LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { LOperand* function = UseFixed(instr->function(), r1); argument_count_ -= instr->argument_count(); - LInvokeFunction* result = new LInvokeFunction(function); + LInvokeFunction* result = new(zone()) LInvokeFunction(function); return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY); } LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { BuiltinFunctionId op = instr->op(); - if (op == kMathLog || op == kMathSin || op == kMathCos) { + if (op == kMathLog || op == kMathSin || op == kMathCos || op == kMathTan) { LOperand* input = UseFixedDouble(instr->value(), d2); - LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL); + LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, NULL); return MarkAsCall(DefineFixedDouble(result, d2), instr); } else if (op == kMathPowHalf) { LOperand* input = UseFixedDouble(instr->value(), d2); LOperand* temp = FixedTemp(d3); - LUnaryMathOperation* result = new LUnaryMathOperation(input, temp); + LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp); return DefineFixedDouble(result, d2); } else { LOperand* input = UseRegisterAtStart(instr->value()); LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; - LUnaryMathOperation* result = new LUnaryMathOperation(input, temp); + LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp); switch (op) { case kMathAbs: return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); @@ -1193,32 +1204,32 @@ LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { ASSERT(instr->key()->representation().IsTagged()); argument_count_ -= instr->argument_count(); LOperand* key = UseFixed(instr->key(), r2); - return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), r0), instr); } LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { argument_count_ -= instr->argument_count(); - return MarkAsCall(DefineFixed(new LCallNamed, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LCallNamed, r0), instr); } LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { argument_count_ -= instr->argument_count(); - return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, r0), instr); } LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { argument_count_ -= instr->argument_count(); - return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, r0), instr); } LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { LOperand* constructor = UseFixed(instr->constructor(), r1); argument_count_ -= instr->argument_count(); - LCallNew* result = new LCallNew(constructor); + LCallNew* result = new(zone()) LCallNew(constructor); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -1226,13 +1237,14 @@ LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { LOperand* function = UseFixed(instr->function(), r1); argument_count_ -= instr->argument_count(); - return MarkAsCall(DefineFixed(new LCallFunction(function), r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), r0), + instr); } LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { argument_count_ -= instr->argument_count(); - return MarkAsCall(DefineFixed(new LCallRuntime, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, r0), instr); } @@ -1258,7 +1270,7 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); - return DefineAsRegister(new LBitI(left, right)); + return DefineAsRegister(new(zone()) LBitI(left, right)); } else { ASSERT(instr->representation().IsTagged()); ASSERT(instr->left()->representation().IsTagged()); @@ -1266,7 +1278,7 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { LOperand* left = UseFixed(instr->left(), r1); LOperand* right = UseFixed(instr->right(), r0); - LArithmeticT* result = new LArithmeticT(instr->op(), left, right); + LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); return MarkAsCall(DefineFixed(result, r0), instr); } } @@ -1275,7 +1287,8 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { ASSERT(instr->value()->representation().IsInteger32()); ASSERT(instr->representation().IsInteger32()); - return DefineAsRegister(new LBitNotI(UseRegisterAtStart(instr->value()))); + LOperand* value = UseRegisterAtStart(instr->value()); + return DefineAsRegister(new(zone()) LBitNotI(value)); } @@ -1291,7 +1304,7 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { LOperand* dividend = UseFixed(instr->left(), r0); LOperand* divisor = UseFixed(instr->right(), r1); return AssignEnvironment(AssignPointerMap( - DefineFixed(new LDivI(dividend, divisor), r0))); + DefineFixed(new(zone()) LDivI(dividend, divisor), r0))); } else { return DoArithmeticT(Token::DIV, instr); } @@ -1307,15 +1320,15 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) { if (instr->HasPowerOf2Divisor()) { ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); LOperand* value = UseRegisterAtStart(instr->left()); - mod = new LModI(value, UseOrConstant(instr->right())); + mod = new(zone()) LModI(value, UseOrConstant(instr->right())); } else { LOperand* dividend = UseRegister(instr->left()); LOperand* divisor = UseRegister(instr->right()); - mod = new LModI(dividend, - divisor, - TempRegister(), - FixedTemp(d10), - FixedTemp(d11)); + mod = new(zone()) LModI(dividend, + divisor, + TempRegister(), + FixedTemp(d10), + FixedTemp(d11)); } if (instr->CheckFlag(HValue::kBailoutOnMinusZero) || @@ -1333,7 +1346,7 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) { // TODO(fschneider): Allow any register as input registers. LOperand* left = UseFixedDouble(instr->left(), d1); LOperand* right = UseFixedDouble(instr->right(), d2); - LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); + LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right); return MarkAsCall(DefineFixedDouble(result, d1), instr); } } @@ -1354,7 +1367,7 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { } else { left = UseRegisterAtStart(instr->LeastConstantOperand()); } - LMulI* mul = new LMulI(left, right, temp); + LMulI* mul = new(zone()) LMulI(left, right, temp); if (instr->CheckFlag(HValue::kCanOverflow) || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { AssignEnvironment(mul); @@ -1376,7 +1389,7 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) { ASSERT(instr->right()->representation().IsInteger32()); LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseOrConstantAtStart(instr->right()); - LSubI* sub = new LSubI(left, right); + LSubI* sub = new(zone()) LSubI(left, right); LInstruction* result = DefineAsRegister(sub); if (instr->CheckFlag(HValue::kCanOverflow)) { result = AssignEnvironment(result); @@ -1396,7 +1409,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { ASSERT(instr->right()->representation().IsInteger32()); LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); - LAddI* add = new LAddI(left, right); + LAddI* add = new(zone()) LAddI(left, right); LInstruction* result = DefineAsRegister(add); if (instr->CheckFlag(HValue::kCanOverflow)) { result = AssignEnvironment(result); @@ -1421,7 +1434,7 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { LOperand* right = exponent_type.IsDouble() ? UseFixedDouble(instr->right(), d2) : UseFixed(instr->right(), r2); - LPower* result = new LPower(left, right); + LPower* result = new(zone()) LPower(left, right); return MarkAsCall(DefineFixedDouble(result, d3), instr, CAN_DEOPTIMIZE_EAGERLY); @@ -1432,7 +1445,7 @@ LInstruction* LChunkBuilder::DoRandom(HRandom* instr) { ASSERT(instr->representation().IsDouble()); ASSERT(instr->global_object()->representation().IsTagged()); LOperand* global_object = UseFixed(instr->global_object(), r0); - LRandom* result = new LRandom(global_object); + LRandom* result = new(zone()) LRandom(global_object); return MarkAsCall(DefineFixedDouble(result, d7), instr); } @@ -1442,7 +1455,7 @@ LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { ASSERT(instr->right()->representation().IsTagged()); LOperand* left = UseFixed(instr->left(), r1); LOperand* right = UseFixed(instr->right(), r0); - LCmpT* result = new LCmpT(left, right); + LCmpT* result = new(zone()) LCmpT(left, right); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -1455,14 +1468,14 @@ LInstruction* LChunkBuilder::DoCompareIDAndBranch( ASSERT(instr->right()->representation().IsInteger32()); LOperand* left = UseRegisterOrConstantAtStart(instr->left()); LOperand* right = UseRegisterOrConstantAtStart(instr->right()); - return new LCmpIDAndBranch(left, right); + return new(zone()) LCmpIDAndBranch(left, right); } else { ASSERT(r.IsDouble()); ASSERT(instr->left()->representation().IsDouble()); ASSERT(instr->right()->representation().IsDouble()); LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseRegisterAtStart(instr->right()); - return new LCmpIDAndBranch(left, right); + return new(zone()) LCmpIDAndBranch(left, right); } } @@ -1471,47 +1484,50 @@ LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( HCompareObjectEqAndBranch* instr) { LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseRegisterAtStart(instr->right()); - return new LCmpObjectEqAndBranch(left, right); + return new(zone()) LCmpObjectEqAndBranch(left, right); } LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch( HCompareConstantEqAndBranch* instr) { - return new LCmpConstantEqAndBranch(UseRegisterAtStart(instr->value())); + LOperand* value = UseRegisterAtStart(instr->value()); + return new(zone()) LCmpConstantEqAndBranch(value); } LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); - return new LIsNilAndBranch(UseRegisterAtStart(instr->value())); + return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value())); } LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); + LOperand* value = UseRegisterAtStart(instr->value()); LOperand* temp = TempRegister(); - return new LIsObjectAndBranch(UseRegisterAtStart(instr->value()), temp); + return new(zone()) LIsObjectAndBranch(value, temp); } LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); + LOperand* value = UseRegisterAtStart(instr->value()); LOperand* temp = TempRegister(); - return new LIsStringAndBranch(UseRegisterAtStart(instr->value()), temp); + return new(zone()) LIsStringAndBranch(value, temp); } LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); - return new LIsSmiAndBranch(Use(instr->value())); + return new(zone()) LIsSmiAndBranch(Use(instr->value())); } LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( HIsUndetectableAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); - return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()), - TempRegister()); + LOperand* value = UseRegisterAtStart(instr->value()); + return new(zone()) LIsUndetectableAndBranch(value, TempRegister()); } @@ -1521,7 +1537,8 @@ LInstruction* LChunkBuilder::DoStringCompareAndBranch( ASSERT(instr->right()->representation().IsTagged()); LOperand* left = UseFixed(instr->left(), r1); LOperand* right = UseFixed(instr->right(), r0); - LStringCompareAndBranch* result = new LStringCompareAndBranch(left, right); + LStringCompareAndBranch* result = + new(zone()) LStringCompareAndBranch(left, right); return MarkAsCall(result, instr); } @@ -1529,7 +1546,8 @@ LInstruction* LChunkBuilder::DoStringCompareAndBranch( LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( HHasInstanceTypeAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); - return new LHasInstanceTypeAndBranch(UseRegisterAtStart(instr->value())); + LOperand* value = UseRegisterAtStart(instr->value()); + return new(zone()) LHasInstanceTypeAndBranch(value); } @@ -1538,14 +1556,14 @@ LInstruction* LChunkBuilder::DoGetCachedArrayIndex( ASSERT(instr->value()->representation().IsTagged()); LOperand* value = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LGetCachedArrayIndex(value)); + return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value)); } LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( HHasCachedArrayIndexAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); - return new LHasCachedArrayIndexAndBranch( + return new(zone()) LHasCachedArrayIndexAndBranch( UseRegisterAtStart(instr->value())); } @@ -1553,40 +1571,48 @@ LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( LInstruction* LChunkBuilder::DoClassOfTestAndBranch( HClassOfTestAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); - return new LClassOfTestAndBranch(UseRegister(instr->value()), - TempRegister()); + LOperand* value = UseRegister(instr->value()); + return new(zone()) LClassOfTestAndBranch(value, TempRegister()); } LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { LOperand* array = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LJSArrayLength(array)); + return DefineAsRegister(new(zone()) LJSArrayLength(array)); } LInstruction* LChunkBuilder::DoFixedArrayBaseLength( HFixedArrayBaseLength* instr) { LOperand* array = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LFixedArrayBaseLength(array)); + return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array)); } LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { LOperand* object = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LElementsKind(object)); + return DefineAsRegister(new(zone()) LElementsKind(object)); } LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { LOperand* object = UseRegister(instr->value()); - LValueOf* result = new LValueOf(object, TempRegister()); + LValueOf* result = new(zone()) LValueOf(object, TempRegister()); return DefineAsRegister(result); } +LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { + LOperand* object = UseFixed(instr->value(), r0); + LDateField* result = new LDateField(object, FixedTemp(r1), instr->index()); + return MarkAsCall(DefineFixed(result, r0), instr); +} + + LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { - return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), - UseRegister(instr->length()))); + LOperand* value = UseRegisterAtStart(instr->index()); + LOperand* length = UseRegister(instr->length()); + return AssignEnvironment(new(zone()) LBoundsCheck(value, length)); } @@ -1599,7 +1625,7 @@ LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { LOperand* value = UseFixed(instr->value(), r0); - return MarkAsCall(new LThrow(value), instr); + return MarkAsCall(new(zone()) LThrow(value), instr); } @@ -1622,7 +1648,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { if (from.IsTagged()) { if (to.IsDouble()) { LOperand* value = UseRegister(instr->value()); - LNumberUntagD* res = new LNumberUntagD(value); + LNumberUntagD* res = new(zone()) LNumberUntagD(value); return AssignEnvironment(DefineAsRegister(res)); } else { ASSERT(to.IsInteger32()); @@ -1630,14 +1656,17 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { bool needs_check = !instr->value()->type().IsSmi(); LInstruction* res = NULL; if (!needs_check) { - res = DefineAsRegister(new LSmiUntag(value, needs_check)); + res = DefineAsRegister(new(zone()) LSmiUntag(value, needs_check)); } else { LOperand* temp1 = TempRegister(); LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL; LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11) : NULL; - res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3)); + res = DefineSameAsFirst(new(zone()) LTaggedToI(value, + temp1, + temp2, + temp3)); res = AssignEnvironment(res); } return res; @@ -1651,16 +1680,15 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { // Make sure that the temp and result_temp registers are // different. LUnallocated* result_temp = TempRegister(); - LNumberTagD* result = new LNumberTagD(value, temp1, temp2); + LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); Define(result, result_temp); return AssignPointerMap(result); } else { ASSERT(to.IsInteger32()); LOperand* value = UseRegister(instr->value()); - LDoubleToI* res = - new LDoubleToI(value, - TempRegister(), - instr->CanTruncateToInt32() ? TempRegister() : NULL); + LOperand* temp1 = TempRegister(); + LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL; + LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2); return AssignEnvironment(DefineAsRegister(res)); } } else if (from.IsInteger32()) { @@ -1668,15 +1696,15 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { HValue* val = instr->value(); LOperand* value = UseRegisterAtStart(val); if (val->HasRange() && val->range()->IsInSmiRange()) { - return DefineAsRegister(new LSmiTag(value)); + return DefineAsRegister(new(zone()) LSmiTag(value)); } else { - LNumberTagI* result = new LNumberTagI(value); + LNumberTagI* result = new(zone()) LNumberTagI(value); return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); } } else { ASSERT(to.IsDouble()); LOperand* value = Use(instr->value()); - return DefineAsRegister(new LInteger32ToDouble(value)); + return DefineAsRegister(new(zone()) LInteger32ToDouble(value)); } } UNREACHABLE(); @@ -1686,13 +1714,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { LOperand* value = UseRegisterAtStart(instr->value()); - return AssignEnvironment(new LCheckNonSmi(value)); + return AssignEnvironment(new(zone()) LCheckNonSmi(value)); } LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { LOperand* value = UseRegisterAtStart(instr->value()); - LInstruction* result = new LCheckInstanceType(value); + LInstruction* result = new(zone()) LCheckInstanceType(value); return AssignEnvironment(result); } @@ -1700,26 +1728,26 @@ LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { LOperand* temp1 = TempRegister(); LOperand* temp2 = TempRegister(); - LInstruction* result = new LCheckPrototypeMaps(temp1, temp2); + LInstruction* result = new(zone()) LCheckPrototypeMaps(temp1, temp2); return AssignEnvironment(result); } LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { LOperand* value = UseRegisterAtStart(instr->value()); - return AssignEnvironment(new LCheckSmi(value)); + return AssignEnvironment(new(zone()) LCheckSmi(value)); } LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { LOperand* value = UseRegisterAtStart(instr->value()); - return AssignEnvironment(new LCheckFunction(value)); + return AssignEnvironment(new(zone()) LCheckFunction(value)); } LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) { LOperand* value = UseRegisterAtStart(instr->value()); - LInstruction* result = new LCheckMap(value); + LInstruction* result = new(zone()) LCheckMap(value); return AssignEnvironment(result); } @@ -1729,57 +1757,32 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { Representation input_rep = value->representation(); LOperand* reg = UseRegister(value); if (input_rep.IsDouble()) { - return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d11))); + return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(d11))); } else if (input_rep.IsInteger32()) { - return DefineAsRegister(new LClampIToUint8(reg)); + return DefineAsRegister(new(zone()) LClampIToUint8(reg)); } else { ASSERT(input_rep.IsTagged()); // Register allocator doesn't (yet) support allocation of double // temps. Reserve d1 explicitly. - LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d11)); + LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(d11)); return AssignEnvironment(DefineAsRegister(result)); } } -LInstruction* LChunkBuilder::DoToInt32(HToInt32* instr) { - HValue* value = instr->value(); - Representation input_rep = value->representation(); - LOperand* reg = UseRegister(value); - if (input_rep.IsDouble()) { - LOperand* temp1 = TempRegister(); - LOperand* temp2 = TempRegister(); - LDoubleToI* res = new LDoubleToI(reg, temp1, temp2); - return AssignEnvironment(DefineAsRegister(res)); - } else if (input_rep.IsInteger32()) { - // Canonicalization should already have removed the hydrogen instruction in - // this case, since it is a noop. - UNREACHABLE(); - return NULL; - } else { - ASSERT(input_rep.IsTagged()); - LOperand* temp1 = TempRegister(); - LOperand* temp2 = TempRegister(); - LOperand* temp3 = FixedTemp(d11); - LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3); - return AssignEnvironment(DefineSameAsFirst(res)); - } -} - - LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { - return new LReturn(UseFixed(instr->value(), r0)); + return new(zone()) LReturn(UseFixed(instr->value(), r0)); } LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { Representation r = instr->representation(); if (r.IsInteger32()) { - return DefineAsRegister(new LConstantI); + return DefineAsRegister(new(zone()) LConstantI); } else if (r.IsDouble()) { - return DefineAsRegister(new LConstantD); + return DefineAsRegister(new(zone()) LConstantD); } else if (r.IsTagged()) { - return DefineAsRegister(new LConstantT); + return DefineAsRegister(new(zone()) LConstantT); } else { UNREACHABLE(); return NULL; @@ -1788,7 +1791,7 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) { - LLoadGlobalCell* result = new LLoadGlobalCell; + LLoadGlobalCell* result = new(zone()) LLoadGlobalCell; return instr->RequiresHoleCheck() ? AssignEnvironment(DefineAsRegister(result)) : DefineAsRegister(result); @@ -1797,7 +1800,7 @@ LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) { LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { LOperand* global_object = UseFixed(instr->global_object(), r0); - LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object); + LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -1807,8 +1810,8 @@ LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { // Use a temp to check the value in the cell in the case where we perform // a hole check. return instr->RequiresHoleCheck() - ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister())) - : new LStoreGlobalCell(value, NULL); + ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister())) + : new(zone()) LStoreGlobalCell(value, NULL); } @@ -1816,14 +1819,15 @@ LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) { LOperand* global_object = UseFixed(instr->global_object(), r1); LOperand* value = UseFixed(instr->value(), r0); LStoreGlobalGeneric* result = - new LStoreGlobalGeneric(global_object, value); + new(zone()) LStoreGlobalGeneric(global_object, value); return MarkAsCall(result, instr); } LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { LOperand* context = UseRegisterAtStart(instr->value()); - LInstruction* result = DefineAsRegister(new LLoadContextSlot(context)); + LInstruction* result = + DefineAsRegister(new(zone()) LLoadContextSlot(context)); return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; } @@ -1838,14 +1842,14 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { context = UseRegister(instr->context()); value = UseRegister(instr->value()); } - LInstruction* result = new LStoreContextSlot(context, value); + LInstruction* result = new(zone()) LStoreContextSlot(context, value); return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; } LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { return DefineAsRegister( - new LLoadNamedField(UseRegisterAtStart(instr->object()))); + new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object()))); } @@ -1854,11 +1858,13 @@ LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic( ASSERT(instr->representation().IsTagged()); if (instr->need_generic()) { LOperand* obj = UseFixed(instr->object(), r0); - LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj); + LLoadNamedFieldPolymorphic* result = + new(zone()) LLoadNamedFieldPolymorphic(obj); return MarkAsCall(DefineFixed(result, r0), instr); } else { LOperand* obj = UseRegisterAtStart(instr->object()); - LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj); + LLoadNamedFieldPolymorphic* result = + new(zone()) LLoadNamedFieldPolymorphic(obj); return AssignEnvironment(DefineAsRegister(result)); } } @@ -1866,7 +1872,7 @@ LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic( LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { LOperand* object = UseFixed(instr->object(), r0); - LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0); + LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), r0); return MarkAsCall(result, instr); } @@ -1874,20 +1880,20 @@ LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { LInstruction* LChunkBuilder::DoLoadFunctionPrototype( HLoadFunctionPrototype* instr) { return AssignEnvironment(DefineAsRegister( - new LLoadFunctionPrototype(UseRegister(instr->function())))); + new(zone()) LLoadFunctionPrototype(UseRegister(instr->function())))); } LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { LOperand* input = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LLoadElements(input)); + return DefineAsRegister(new(zone()) LLoadElements(input)); } LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( HLoadExternalArrayPointer* instr) { LOperand* input = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LLoadExternalArrayPointer(input)); + return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); } @@ -1897,7 +1903,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( ASSERT(instr->key()->representation().IsInteger32()); LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* key = UseRegisterAtStart(instr->key()); - LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); + LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key); if (instr->RequiresHoleCheck()) AssignEnvironment(result); return DefineAsRegister(result); } @@ -1910,7 +1916,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement( LOperand* elements = UseTempRegister(instr->elements()); LOperand* key = UseRegisterOrConstantAtStart(instr->key()); LLoadKeyedFastDoubleElement* result = - new LLoadKeyedFastDoubleElement(elements, key); + new(zone()) LLoadKeyedFastDoubleElement(elements, key); return AssignEnvironment(DefineAsRegister(result)); } @@ -1929,7 +1935,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( LOperand* external_pointer = UseRegister(instr->external_pointer()); LOperand* key = UseRegisterOrConstant(instr->key()); LLoadKeyedSpecializedArrayElement* result = - new LLoadKeyedSpecializedArrayElement(external_pointer, key); + new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key); LInstruction* load_instr = DefineAsRegister(result); // An unsigned int array load might overflow and cause a deopt, make sure it // has an environment. @@ -1943,7 +1949,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { LOperand* key = UseFixed(instr->key(), r0); LInstruction* result = - DefineFixed(new LLoadKeyedGeneric(object, key), r0); + DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r0); return MarkAsCall(result, instr); } @@ -1962,7 +1968,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement( LOperand* key = needs_write_barrier ? UseTempRegister(instr->key()) : UseRegisterOrConstantAtStart(instr->key()); - return new LStoreKeyedFastElement(obj, key, val); + return new(zone()) LStoreKeyedFastElement(obj, key, val); } @@ -1976,7 +1982,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement( LOperand* val = UseTempRegister(instr->value()); LOperand* key = UseRegisterOrConstantAtStart(instr->key()); - return new LStoreKeyedFastDoubleElement(elements, key, val); + return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val); } @@ -2002,9 +2008,9 @@ LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( : UseRegister(instr->value()); LOperand* key = UseRegisterOrConstant(instr->key()); - return new LStoreKeyedSpecializedArrayElement(external_pointer, - key, - val); + return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer, + key, + val); } @@ -2017,7 +2023,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { ASSERT(instr->key()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged()); - return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); + return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr); } @@ -2028,14 +2034,16 @@ LInstruction* LChunkBuilder::DoTransitionElementsKind( LOperand* object = UseRegister(instr->object()); LOperand* new_map_reg = TempRegister(); LTransitionElementsKind* result = - new LTransitionElementsKind(object, new_map_reg, NULL); + new(zone()) LTransitionElementsKind(object, new_map_reg, NULL); return DefineSameAsFirst(result); } else { LOperand* object = UseFixed(instr->object(), r0); LOperand* fixed_object_reg = FixedTemp(r2); LOperand* new_map_reg = FixedTemp(r3); LTransitionElementsKind* result = - new LTransitionElementsKind(object, new_map_reg, fixed_object_reg); + new(zone()) LTransitionElementsKind(object, + new_map_reg, + fixed_object_reg); return MarkAsCall(DefineFixed(result, r0), instr); } } @@ -2052,7 +2060,7 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { ? UseTempRegister(instr->value()) : UseRegister(instr->value()); - return new LStoreNamedField(obj, val); + return new(zone()) LStoreNamedField(obj, val); } @@ -2060,7 +2068,7 @@ LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { LOperand* obj = UseFixed(instr->object(), r1); LOperand* val = UseFixed(instr->value(), r0); - LInstruction* result = new LStoreNamedGeneric(obj, val); + LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val); return MarkAsCall(result, instr); } @@ -2068,60 +2076,67 @@ LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseRegisterAtStart(instr->right()); - return MarkAsCall(DefineFixed(new LStringAdd(left, right), r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), r0), + instr); } LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { LOperand* string = UseTempRegister(instr->string()); LOperand* index = UseTempRegister(instr->index()); - LStringCharCodeAt* result = new LStringCharCodeAt(string, index); + LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index); return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); } LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { LOperand* char_code = UseRegister(instr->value()); - LStringCharFromCode* result = new LStringCharFromCode(char_code); + LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code); return AssignPointerMap(DefineAsRegister(result)); } LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { LOperand* string = UseRegisterAtStart(instr->value()); - return DefineAsRegister(new LStringLength(string)); + return DefineAsRegister(new(zone()) LStringLength(string)); +} + + +LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { + LAllocateObject* result = new LAllocateObject(TempRegister(), TempRegister()); + return AssignPointerMap(DefineAsRegister(result)); } LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) { - return MarkAsCall(DefineFixed(new LFastLiteral, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, r0), instr); } LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { - return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, r0), instr); } LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { - return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, r0), instr); } LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { - return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, r0), instr); } LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { - return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, r0), instr); } LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { LOperand* object = UseFixed(instr->object(), r0); LOperand* key = UseFixed(instr->key(), r1); - LDeleteProperty* result = new LDeleteProperty(object, key); + LDeleteProperty* result = new(zone()) LDeleteProperty(object, key); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -2129,13 +2144,13 @@ LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { allocator_->MarkAsOsrEntry(); current_block_->last_environment()->set_ast_id(instr->ast_id()); - return AssignEnvironment(new LOsrEntry); + return AssignEnvironment(new(zone()) LOsrEntry); } LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { int spill_index = chunk()->GetParameterStackSlot(instr->index()); - return DefineAsSpilled(new LParameter, spill_index); + return DefineAsSpilled(new(zone()) LParameter, spill_index); } @@ -2145,13 +2160,13 @@ LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { Abort("Too many spill slots needed for OSR"); spill_index = 0; } - return DefineAsSpilled(new LUnknownOSRValue, spill_index); + return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index); } LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { argument_count_ -= instr->argument_count(); - return MarkAsCall(DefineFixed(new LCallStub, r0), instr); + return MarkAsCall(DefineFixed(new(zone()) LCallStub, r0), instr); } @@ -2168,32 +2183,33 @@ LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { LOperand* arguments = UseRegister(instr->arguments()); LOperand* length = UseTempRegister(instr->length()); LOperand* index = UseRegister(instr->index()); - LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index); + LAccessArgumentsAt* result = + new(zone()) LAccessArgumentsAt(arguments, length, index); return AssignEnvironment(DefineAsRegister(result)); } LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) { LOperand* object = UseFixed(instr->value(), r0); - LToFastProperties* result = new LToFastProperties(object); + LToFastProperties* result = new(zone()) LToFastProperties(object); return MarkAsCall(DefineFixed(result, r0), instr); } LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { - LTypeof* result = new LTypeof(UseFixed(instr->value(), r0)); + LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), r0)); return MarkAsCall(DefineFixed(result, r0), instr); } LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { - return new LTypeofIsAndBranch(UseTempRegister(instr->value())); + return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value())); } LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( HIsConstructCallAndBranch* instr) { - return new LIsConstructCallAndBranch(TempRegister()); + return new(zone()) LIsConstructCallAndBranch(TempRegister()); } @@ -2216,7 +2232,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { // 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 LLazyBailout; + LInstruction* result = new(zone()) LLazyBailout; result = AssignEnvironment(result); instruction_pending_deoptimization_environment_-> set_deoptimization_environment(result->environment()); @@ -2230,10 +2246,10 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { if (instr->is_function_entry()) { - return MarkAsCall(new LStackCheck, instr); + return MarkAsCall(new(zone()) LStackCheck, instr); } else { ASSERT(instr->is_backwards_branch()); - return AssignEnvironment(AssignPointerMap(new LStackCheck)); + return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck)); } } @@ -2245,7 +2261,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { instr->arguments_count(), instr->function(), undefined, - instr->call_kind()); + instr->call_kind(), + instr->is_construct()); current_block_->UpdateEnvironment(inner); chunk_->AddInlinedClosure(instr->closure()); return NULL; @@ -2263,14 +2280,14 @@ LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { LInstruction* LChunkBuilder::DoIn(HIn* instr) { LOperand* key = UseRegisterAtStart(instr->key()); LOperand* object = UseRegisterAtStart(instr->object()); - LIn* result = new LIn(key, object); + LIn* result = new(zone()) LIn(key, object); return MarkAsCall(DefineFixed(result, r0), instr); } LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { LOperand* object = UseFixed(instr->enumerable(), r0); - LForInPrepareMap* result = new LForInPrepareMap(object); + LForInPrepareMap* result = new(zone()) LForInPrepareMap(object); return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); } @@ -2278,21 +2295,21 @@ LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) { LOperand* map = UseRegister(instr->map()); return AssignEnvironment(DefineAsRegister( - new LForInCacheArray(map))); + new(zone()) LForInCacheArray(map))); } LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) { LOperand* value = UseRegisterAtStart(instr->value()); LOperand* map = UseRegisterAtStart(instr->map()); - return AssignEnvironment(new LCheckMapValue(value, map)); + return AssignEnvironment(new(zone()) LCheckMapValue(value, map)); } LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { LOperand* object = UseRegister(instr->object()); LOperand* index = UseRegister(instr->index()); - return DefineAsRegister(new LLoadFieldByIndex(object, index)); + return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); } diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h index 1846922dbc..ae19677fda 100644 --- a/deps/v8/src/arm/lithium-arm.h +++ b/deps/v8/src/arm/lithium-arm.h @@ -49,6 +49,7 @@ class LCodeGen; #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \ V(AccessArgumentsAt) \ V(AddI) \ + V(AllocateObject) \ V(ApplyArguments) \ V(ArgumentsElements) \ V(ArgumentsLength) \ @@ -176,8 +177,8 @@ class LCodeGen; V(ForInPrepareMap) \ V(ForInCacheArray) \ V(CheckMapValue) \ - V(LoadFieldByIndex) - + V(LoadFieldByIndex) \ + V(DateField) #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \ @@ -989,6 +990,41 @@ class LValueOf: public LTemplateInstruction<1, 1, 1> { }; +class LDateField: public LTemplateInstruction<1, 1, 1> { + public: + LDateField(LOperand* date, LOperand* temp, Smi* index) : index_(index) { + inputs_[0] = date; + temps_[0] = temp; + } + + DECLARE_CONCRETE_INSTRUCTION(ValueOf, "date-field") + DECLARE_HYDROGEN_ACCESSOR(ValueOf) + Smi* index() const { return index_; } + + private: + Smi* index_; +}; + + +class LSetDateField: public LTemplateInstruction<1, 2, 1> { + public: + LSetDateField(LOperand* date, LOperand* value, LOperand* temp, int index) + : index_(index) { + inputs_[0] = date; + inputs_[1] = value; + temps_[0] = temp; + } + + DECLARE_CONCRETE_INSTRUCTION(DateField, "date-set-field") + DECLARE_HYDROGEN_ACCESSOR(DateField) + + int index() const { return index_; } + + private: + int index_; +}; + + class LThrow: public LTemplateInstruction<0, 1, 0> { public: explicit LThrow(LOperand* value) { @@ -1922,6 +1958,18 @@ class LClampTToUint8: public LTemplateInstruction<1, 1, 1> { }; +class LAllocateObject: public LTemplateInstruction<1, 0, 2> { + public: + LAllocateObject(LOperand* temp1, LOperand* temp2) { + temps_[0] = temp1; + temps_[1] = temp2; + } + + DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object") + DECLARE_HYDROGEN_ACCESSOR(AllocateObject) +}; + + class LFastLiteral: public LTemplateInstruction<1, 0, 0> { public: DECLARE_CONCRETE_INSTRUCTION(FastLiteral, "fast-literal") @@ -2192,6 +2240,7 @@ class LChunkBuilder BASE_EMBEDDED { : chunk_(NULL), info_(info), graph_(graph), + zone_(graph->isolate()->zone()), status_(UNUSED), current_instruction_(NULL), current_block_(NULL), @@ -2221,6 +2270,7 @@ class LChunkBuilder BASE_EMBEDDED { LChunk* chunk() const { return chunk_; } CompilationInfo* info() const { return info_; } HGraph* graph() const { return graph_; } + Zone* zone() const { return zone_; } bool is_unused() const { return status_ == UNUSED; } bool is_building() const { return status_ == BUILDING; } @@ -2325,6 +2375,7 @@ class LChunkBuilder BASE_EMBEDDED { LChunk* chunk_; CompilationInfo* info_; HGraph* const graph_; + Zone* zone_; Status status_; HInstruction* current_instruction_; HBasicBlock* current_block_; diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index 8045556406..012ea458ff 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -62,7 +62,7 @@ class SafepointGenerator : public CallWrapper { #define __ masm()-> bool LCodeGen::GenerateCode() { - HPhase phase("Code generation", chunk()); + HPhase phase("Z_Code generation", chunk()); ASSERT(is_unused()); status_ = GENERATING; CpuFeatures::Scope scope1(VFP3); @@ -479,10 +479,18 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, WriteTranslation(environment->outer(), translation); int closure_id = DefineDeoptimizationLiteral(environment->closure()); - if (environment->is_arguments_adaptor()) { - translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); - } else { - translation->BeginJSFrame(environment->ast_id(), closure_id, height); + switch (environment->frame_type()) { + case JS_FUNCTION: + translation->BeginJSFrame(environment->ast_id(), closure_id, height); + break; + case JS_CONSTRUCT: + translation->BeginConstructStubFrame(closure_id, translation_size); + break; + case ARGUMENTS_ADAPTOR: + translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); + break; + default: + UNREACHABLE(); } for (int i = 0; i < translation_size; ++i) { LOperand* value = environment->values()->at(i); @@ -619,7 +627,7 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, int jsframe_count = 0; for (LEnvironment* e = environment; e != NULL; e = e->outer()) { ++frame_count; - if (!e->is_arguments_adaptor()) { + if (e->frame_type() == JS_FUNCTION) { ++jsframe_count; } } @@ -1430,6 +1438,46 @@ void LCodeGen::DoValueOf(LValueOf* instr) { } +void LCodeGen::DoDateField(LDateField* instr) { + Register object = ToRegister(instr->InputAt(0)); + Register result = ToRegister(instr->result()); + Register scratch = ToRegister(instr->TempAt(0)); + Smi* index = instr->index(); + Label runtime, done; + ASSERT(object.is(result)); + ASSERT(object.is(r0)); + ASSERT(!scratch.is(scratch0())); + ASSERT(!scratch.is(object)); + +#ifdef DEBUG + __ AbortIfSmi(object); + __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); + __ Assert(eq, "Trying to get date field from non-date."); +#endif + + if (index->value() == 0) { + __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); + } else { + if (index->value() < JSDate::kFirstUncachedField) { + ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); + __ mov(scratch, Operand(stamp)); + __ ldr(scratch, MemOperand(scratch)); + __ ldr(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); + __ cmp(scratch, scratch0()); + __ b(ne, &runtime); + __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset + + kPointerSize * index->value())); + __ jmp(&done); + } + __ bind(&runtime); + __ PrepareCallCFunction(2, scratch); + __ mov(r1, Operand(index)); + __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); + __ bind(&done); + } +} + + void LCodeGen::DoBitNotI(LBitNotI* instr) { Register input = ToRegister(instr->InputAt(0)); Register result = ToRegister(instr->result()); @@ -3222,15 +3270,62 @@ void LCodeGen::DoPower(LPower* instr) { void LCodeGen::DoRandom(LRandom* instr) { + class DeferredDoRandom: public LDeferredCode { + public: + DeferredDoRandom(LCodeGen* codegen, LRandom* instr) + : LDeferredCode(codegen), instr_(instr) { } + virtual void Generate() { codegen()->DoDeferredRandom(instr_); } + virtual LInstruction* instr() { return instr_; } + private: + LRandom* instr_; + }; + + DeferredDoRandom* deferred = new DeferredDoRandom(this, instr); + // Having marked this instruction as a call we can use any // registers. ASSERT(ToDoubleRegister(instr->result()).is(d7)); ASSERT(ToRegister(instr->InputAt(0)).is(r0)); - __ PrepareCallCFunction(1, scratch0()); + static const int kSeedSize = sizeof(uint32_t); + STATIC_ASSERT(kPointerSize == kSeedSize); + __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); - __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); + static const int kRandomSeedOffset = + FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; + __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset)); + // r2: FixedArray of the global context's random seeds + + // Load state[0]. + __ ldr(r1, FieldMemOperand(r2, ByteArray::kHeaderSize)); + __ cmp(r1, Operand(0)); + __ b(eq, deferred->entry()); + // Load state[1]. + __ ldr(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize)); + // r1: state[0]. + // r0: state[1]. + + // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) + __ and_(r3, r1, Operand(0xFFFF)); + __ mov(r4, Operand(18273)); + __ mul(r3, r3, r4); + __ add(r1, r3, Operand(r1, LSR, 16)); + // Save state[0]. + __ str(r1, FieldMemOperand(r2, ByteArray::kHeaderSize)); + + // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16) + __ and_(r3, r0, Operand(0xFFFF)); + __ mov(r4, Operand(36969)); + __ mul(r3, r3, r4); + __ add(r0, r3, Operand(r0, LSR, 16)); + // Save state[1]. + __ str(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize)); + + // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) + __ and_(r0, r0, Operand(0x3FFFF)); + __ add(r0, r0, Operand(r1, LSL, 14)); + __ bind(deferred->exit()); // 0x41300000 is the top half of 1.0 x 2^20 as a double. // Create this constant using mov/orr to avoid PC relative load. __ mov(r1, Operand(0x41000000)); @@ -3245,6 +3340,13 @@ void LCodeGen::DoRandom(LRandom* instr) { } +void LCodeGen::DoDeferredRandom(LRandom* instr) { + __ PrepareCallCFunction(1, scratch0()); + __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); + // Return value is in r0. +} + + void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { ASSERT(ToDoubleRegister(instr->result()).is(d2)); TranscendentalCacheStub stub(TranscendentalCache::LOG, @@ -4322,6 +4424,80 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } +void LCodeGen::DoAllocateObject(LAllocateObject* instr) { + class DeferredAllocateObject: public LDeferredCode { + public: + DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) + : LDeferredCode(codegen), instr_(instr) { } + virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } + virtual LInstruction* instr() { return instr_; } + private: + LAllocateObject* instr_; + }; + + DeferredAllocateObject* deferred = new DeferredAllocateObject(this, instr); + + Register result = ToRegister(instr->result()); + Register scratch = ToRegister(instr->TempAt(0)); + Register scratch2 = ToRegister(instr->TempAt(1)); + Handle<JSFunction> constructor = instr->hydrogen()->constructor(); + Handle<Map> initial_map(constructor->initial_map()); + int instance_size = initial_map->instance_size(); + ASSERT(initial_map->pre_allocated_property_fields() + + initial_map->unused_property_fields() - + initial_map->inobject_properties() == 0); + + // Allocate memory for the object. The initial map might change when + // the constructor's prototype changes, but instance size and property + // counts remain unchanged (if slack tracking finished). + ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress()); + __ AllocateInNewSpace(instance_size, + result, + scratch, + scratch2, + deferred->entry(), + TAG_OBJECT); + + // Load the initial map. + Register map = scratch; + __ LoadHeapObject(map, constructor); + __ ldr(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset)); + + // Initialize map and fields of the newly allocated object. + ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); + __ str(map, FieldMemOperand(result, JSObject::kMapOffset)); + __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex); + __ str(scratch, FieldMemOperand(result, JSObject::kElementsOffset)); + __ str(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset)); + if (initial_map->inobject_properties() != 0) { + __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); + for (int i = 0; i < initial_map->inobject_properties(); i++) { + int property_offset = JSObject::kHeaderSize + i * kPointerSize; + __ str(scratch, FieldMemOperand(result, property_offset)); + } + } + + __ bind(deferred->exit()); +} + + +void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { + Register result = ToRegister(instr->result()); + Handle<JSFunction> constructor = instr->hydrogen()->constructor(); + + // TODO(3095996): Get rid of this. For now, we need to make the + // result register contain a valid pointer because it is already + // contained in the register pointer map. + __ mov(result, Operand(0)); + + PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + __ LoadHeapObject(r0, constructor); + __ push(r0); + CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr); + __ StoreToSafepointRegisterSlot(r0, result); +} + + void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { Heap* heap = isolate()->heap(); ElementsKind boilerplate_elements_kind = diff --git a/deps/v8/src/arm/lithium-codegen-arm.h b/deps/v8/src/arm/lithium-codegen-arm.h index 00823e1638..adb6e1bb73 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.h +++ b/deps/v8/src/arm/lithium-codegen-arm.h @@ -114,8 +114,10 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredTaggedToI(LTaggedToI* instr); void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr); void DoDeferredStackCheck(LStackCheck* instr); + void DoDeferredRandom(LRandom* instr); void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); void DoDeferredStringCharFromCode(LStringCharFromCode* instr); + void DoDeferredAllocateObject(LAllocateObject* instr); void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); diff --git a/deps/v8/src/arm/regexp-macro-assembler-arm.cc b/deps/v8/src/arm/regexp-macro-assembler-arm.cc index 880c372538..de83c13e15 100644 --- a/deps/v8/src/arm/regexp-macro-assembler-arm.cc +++ b/deps/v8/src/arm/regexp-macro-assembler-arm.cc @@ -1055,7 +1055,7 @@ int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address, ASSERT(*return_address <= re_code->instruction_start() + re_code->instruction_size()); - MaybeObject* result = Execution::HandleStackGuardInterrupt(); + MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate); if (*code_handle != re_code) { // Return address no longer valid int delta = code_handle->address() - re_code->address(); diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc index 9a0793e12f..74fca2e4c5 100644 --- a/deps/v8/src/arm/stub-cache-arm.cc +++ b/deps/v8/src/arm/stub-cache-arm.cc @@ -43,59 +43,83 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm, Code::Flags flags, StubCache::Table table, + Register receiver, Register name, + // Number of the cache entry, not scaled. Register offset, - int offset_shift_bits, Register scratch, - Register scratch2) { + Register scratch2, + Register offset_scratch) { ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); + ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address()); uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address()); + uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address()); // Check the relative positions of the address fields. ASSERT(value_off_addr > key_off_addr); ASSERT((value_off_addr - key_off_addr) % 4 == 0); ASSERT((value_off_addr - key_off_addr) < (256 * 4)); + ASSERT(map_off_addr > key_off_addr); + ASSERT((map_off_addr - key_off_addr) % 4 == 0); + ASSERT((map_off_addr - key_off_addr) < (256 * 4)); Label miss; - Register offsets_base_addr = scratch; + Register base_addr = scratch; + scratch = no_reg; + + // Multiply by 3 because there are 3 fields per entry (name, code, map). + __ add(offset_scratch, offset, Operand(offset, LSL, 1)); + + // Calculate the base address of the entry. + __ mov(base_addr, Operand(key_offset)); + __ add(base_addr, base_addr, Operand(offset_scratch, LSL, kPointerSizeLog2)); // Check that the key in the entry matches the name. - __ mov(offsets_base_addr, Operand(key_offset)); - __ ldr(ip, MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits)); + __ ldr(ip, MemOperand(base_addr, 0)); __ cmp(name, ip); __ b(ne, &miss); + // Check the map matches. + __ ldr(ip, MemOperand(base_addr, map_off_addr - key_off_addr)); + __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); + __ cmp(ip, scratch2); + __ b(ne, &miss); + // Get the code entry from the cache. - __ add(offsets_base_addr, offsets_base_addr, - Operand(value_off_addr - key_off_addr)); - __ ldr(scratch2, - MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits)); + Register code = scratch2; + scratch2 = no_reg; + __ ldr(code, MemOperand(base_addr, value_off_addr - key_off_addr)); // Check that the flags match what we're looking for. - __ ldr(scratch2, FieldMemOperand(scratch2, Code::kFlagsOffset)); + Register flags_reg = base_addr; + base_addr = no_reg; + __ ldr(flags_reg, FieldMemOperand(code, Code::kFlagsOffset)); // It's a nice optimization if this constant is encodable in the bic insn. uint32_t mask = Code::kFlagsNotUsedInLookup; ASSERT(__ ImmediateFitsAddrMode1Instruction(mask)); - __ bic(scratch2, scratch2, Operand(mask)); + __ bic(flags_reg, flags_reg, Operand(mask)); // Using cmn and the negative instead of cmp means we can use movw. if (flags < 0) { - __ cmn(scratch2, Operand(-flags)); + __ cmn(flags_reg, Operand(-flags)); } else { - __ cmp(scratch2, Operand(flags)); + __ cmp(flags_reg, Operand(flags)); } __ b(ne, &miss); - // Re-load code entry from cache. - __ ldr(offset, - MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits)); +#ifdef DEBUG + if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { + __ jmp(&miss); + } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { + __ jmp(&miss); + } +#endif // Jump to the first instruction in the code stub. - __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag)); - __ Jump(offset); + __ add(pc, code, Operand(Code::kHeaderSize - kHeapObjectTag)); // Miss: fall through. __ bind(&miss); @@ -167,13 +191,14 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Register name, Register scratch, Register extra, - Register extra2) { + Register extra2, + Register extra3) { Isolate* isolate = masm->isolate(); Label miss; - // Make sure that code is valid. The shifting code relies on the - // entry size being 8. - ASSERT(sizeof(Entry) == 8); + // Make sure that code is valid. The multiplying code relies on the + // entry size being 12. + ASSERT(sizeof(Entry) == 12); // Make sure the flags does not name a specific type. ASSERT(Code::ExtractTypeFromFlags(flags) == 0); @@ -193,6 +218,11 @@ void StubCache::GenerateProbe(MacroAssembler* masm, ASSERT(!scratch.is(no_reg)); ASSERT(!extra.is(no_reg)); ASSERT(!extra2.is(no_reg)); + ASSERT(!extra3.is(no_reg)); + + Counters* counters = masm->isolate()->counters(); + __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, + extra2, extra3); // Check that the receiver isn't a smi. __ JumpIfSmi(receiver, &miss); @@ -201,29 +231,32 @@ void StubCache::GenerateProbe(MacroAssembler* masm, __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); __ add(scratch, scratch, Operand(ip)); - uint32_t mask = (kPrimaryTableSize - 1) << kHeapObjectTagSize; + uint32_t mask = kPrimaryTableSize - 1; + // We shift out the last two bits because they are not part of the hash and + // they are always 01 for maps. + __ mov(scratch, Operand(scratch, LSR, kHeapObjectTagSize)); // Mask down the eor argument to the minimum to keep the immediate // ARM-encodable. - __ eor(scratch, scratch, Operand(flags & mask)); + __ eor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask)); // Prefer and_ to ubfx here because ubfx takes 2 cycles. __ and_(scratch, scratch, Operand(mask)); - __ mov(scratch, Operand(scratch, LSR, 1)); // Probe the primary table. ProbeTable(isolate, masm, flags, kPrimary, + receiver, name, scratch, - 1, extra, - extra2); + extra2, + extra3); // Primary miss: Compute hash for secondary probe. - __ sub(scratch, scratch, Operand(name, LSR, 1)); - uint32_t mask2 = (kSecondaryTableSize - 1) << (kHeapObjectTagSize - 1); - __ add(scratch, scratch, Operand((flags >> 1) & mask2)); + __ sub(scratch, scratch, Operand(name, LSR, kHeapObjectTagSize)); + uint32_t mask2 = kSecondaryTableSize - 1; + __ add(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2)); __ and_(scratch, scratch, Operand(mask2)); // Probe the secondary table. @@ -231,15 +264,18 @@ void StubCache::GenerateProbe(MacroAssembler* masm, masm, flags, kSecondary, + receiver, name, scratch, - 1, extra, - extra2); + extra2, + extra3); // Cache miss: Fall-through and let caller handle the miss by // entering the runtime system. __ bind(&miss); + __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, + extra2, extra3); } |