diff options
author | Refael Ackermann <refack@gmail.com> | 2014-09-29 13:20:04 +0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2014-10-08 15:44:38 +0400 |
commit | 9116b240c924d37627313416b7ee038d0580afbc (patch) | |
tree | 86c586915a96d308b1b04de679a8ae293caf3e41 /deps/v8/src/ia32/lithium-codegen-ia32.cc | |
parent | a2a3fd48934f36d94575dd33d2a2cb732f937f77 (diff) | |
download | node-9116b240c924d37627313416b7ee038d0580afbc.tar.gz |
deps: update v8 to 3.28.73
Reviewed-By: Fedor Indutny <fedor@indutny.com>
PR-URL: https://github.com/joyent/node/pull/8476
Diffstat (limited to 'deps/v8/src/ia32/lithium-codegen-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/lithium-codegen-ia32.cc | 1778 |
1 files changed, 520 insertions, 1258 deletions
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index d2b4f2f7d..245dcdc48 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -2,29 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "v8.h" +#include "src/v8.h" #if V8_TARGET_ARCH_IA32 -#include "ia32/lithium-codegen-ia32.h" -#include "ic.h" -#include "code-stubs.h" -#include "deoptimizer.h" -#include "stub-cache.h" -#include "codegen.h" -#include "hydrogen-osr.h" +#include "src/code-stubs.h" +#include "src/codegen.h" +#include "src/deoptimizer.h" +#include "src/hydrogen-osr.h" +#include "src/ia32/lithium-codegen-ia32.h" +#include "src/ic.h" +#include "src/stub-cache.h" namespace v8 { namespace internal { - -static SaveFPRegsMode GetSaveFPRegsMode(Isolate* isolate) { - // We don't need to save floating point regs when generating the snapshot - return CpuFeatures::IsSafeForSnapshot(isolate, SSE2) ? kSaveFPRegs - : kDontSaveFPRegs; -} - - // When invoking builtins, we need to record the safepoint in the middle of // the invoke instruction sequence generated by the macro assembler. class SafepointGenerator V8_FINAL : public CallWrapper { @@ -54,7 +46,7 @@ class SafepointGenerator V8_FINAL : public CallWrapper { bool LCodeGen::GenerateCode() { LPhase phase("Z_Code generation", chunk()); - ASSERT(is_unused()); + DCHECK(is_unused()); status_ = GENERATING; // Open a frame scope to indicate that there is a frame on the stack. The @@ -78,7 +70,7 @@ bool LCodeGen::GenerateCode() { void LCodeGen::FinishCode(Handle<Code> code) { - ASSERT(is_done()); + DCHECK(is_done()); code->set_stack_slots(GetStackSlotCount()); code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); @@ -100,10 +92,9 @@ void LCodeGen::MakeSureStackPagesMapped(int offset) { void LCodeGen::SaveCallerDoubles() { - ASSERT(info()->saves_caller_doubles()); - ASSERT(NeedsEagerFrame()); + DCHECK(info()->saves_caller_doubles()); + DCHECK(NeedsEagerFrame()); Comment(";;; Save clobbered callee double registers"); - CpuFeatureScope scope(masm(), SSE2); int count = 0; BitVector* doubles = chunk()->allocated_double_registers(); BitVector::Iterator save_iterator(doubles); @@ -117,10 +108,9 @@ void LCodeGen::SaveCallerDoubles() { void LCodeGen::RestoreCallerDoubles() { - ASSERT(info()->saves_caller_doubles()); - ASSERT(NeedsEagerFrame()); + DCHECK(info()->saves_caller_doubles()); + DCHECK(NeedsEagerFrame()); Comment(";;; Restore clobbered callee double registers"); - CpuFeatureScope scope(masm(), SSE2); BitVector* doubles = chunk()->allocated_double_registers(); BitVector::Iterator save_iterator(doubles); int count = 0; @@ -134,7 +124,7 @@ void LCodeGen::RestoreCallerDoubles() { bool LCodeGen::GeneratePrologue() { - ASSERT(is_generating()); + DCHECK(is_generating()); if (info()->IsOptimizing()) { ProfileEntryHookStub::MaybeCallEntryHook(masm_); @@ -161,7 +151,7 @@ bool LCodeGen::GeneratePrologue() { __ j(not_equal, &ok, Label::kNear); __ mov(ecx, GlobalObjectOperand()); - __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); + __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset)); __ mov(Operand(esp, receiver_offset), ecx); @@ -196,9 +186,13 @@ bool LCodeGen::GeneratePrologue() { info()->set_prologue_offset(masm_->pc_offset()); if (NeedsEagerFrame()) { - ASSERT(!frame_is_built_); + DCHECK(!frame_is_built_); frame_is_built_ = true; - __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); + if (info()->IsStub()) { + __ StubPrologue(); + } else { + __ Prologue(info()->IsCodePreAgingActive()); + } info()->AddNoFrameRange(0, masm_->pc_offset()); } @@ -211,7 +205,7 @@ bool LCodeGen::GeneratePrologue() { // Reserve space for the stack slots needed by the code. int slots = GetStackSlotCount(); - ASSERT(slots != 0 || !info()->IsOptimizing()); + DCHECK(slots != 0 || !info()->IsOptimizing()); if (slots > 0) { if (slots == 1) { if (dynamic_frame_alignment_) { @@ -253,22 +247,23 @@ bool LCodeGen::GeneratePrologue() { } } - if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { - SaveCallerDoubles(); - } + if (info()->saves_caller_doubles()) SaveCallerDoubles(); } // Possibly allocate a local context. int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; if (heap_slots > 0) { Comment(";;; Allocate local context"); + bool need_write_barrier = true; // Argument to NewContext is the function, which is still in edi. if (heap_slots <= FastNewContextStub::kMaximumSlots) { FastNewContextStub stub(isolate(), heap_slots); __ CallStub(&stub); + // Result of FastNewContextStub is always in new space. + need_write_barrier = false; } else { __ push(edi); - __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } RecordSafepoint(Safepoint::kNoLazyDeopt); // Context is returned in eax. It replaces the context passed to us. @@ -289,11 +284,18 @@ bool LCodeGen::GeneratePrologue() { int context_offset = Context::SlotOffset(var->index()); __ mov(Operand(esi, context_offset), eax); // Update the write barrier. This clobbers eax and ebx. - __ RecordWriteContextSlot(esi, - context_offset, - eax, - ebx, - kDontSaveFPRegs); + if (need_write_barrier) { + __ RecordWriteContextSlot(esi, + context_offset, + eax, + ebx, + kDontSaveFPRegs); + } else if (FLAG_debug_code) { + Label done; + __ JumpIfInNewSpace(esi, eax, &done, Label::kNear); + __ Abort(kExpectedNewSpaceObject); + __ bind(&done); + } } } Comment(";;; End allocate local context"); @@ -355,7 +357,7 @@ void LCodeGen::GenerateOsrPrologue() { // Adjust the frame size, subsuming the unoptimized frame into the // optimized frame. int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); - ASSERT(slots >= 1); + DCHECK(slots >= 1); __ sub(esp, Immediate((slots - 1) * kPointerSize)); } @@ -367,27 +369,10 @@ void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { if (!instr->IsLazyBailout() && !instr->IsGap()) { safepoints_.BumpLastLazySafepointIndex(); } - if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr); } -void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { - if (!CpuFeatures::IsSupported(SSE2)) { - if (instr->IsGoto()) { - x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr)); - } else if (FLAG_debug_code && FLAG_enable_slow_asserts && - !instr->IsGap() && !instr->IsReturn()) { - if (instr->ClobbersDoubleRegisters(isolate())) { - if (instr->HasDoubleRegisterResult()) { - ASSERT_EQ(1, x87_stack_.depth()); - } else { - ASSERT_EQ(0, x87_stack_.depth()); - } - } - __ VerifyX87StackDepth(x87_stack_.depth()); - } - } -} +void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { } bool LCodeGen::GenerateJumpTable() { @@ -406,7 +391,7 @@ bool LCodeGen::GenerateJumpTable() { Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); } if (jump_table_[i].needs_frame) { - ASSERT(!info()->saves_caller_doubles()); + DCHECK(!info()->saves_caller_doubles()); __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); if (needs_frame.is_bound()) { __ jmp(&needs_frame); @@ -416,7 +401,7 @@ bool LCodeGen::GenerateJumpTable() { // This variant of deopt can only be used with stubs. Since we don't // have a function pointer to install in the stack frame that we're // building, install a special marker there instead. - ASSERT(info()->IsStub()); + DCHECK(info()->IsStub()); __ push(Immediate(Smi::FromInt(StackFrame::STUB))); // Push a PC inside the function so that the deopt code can find where // the deopt comes from. It doesn't have to be the precise return @@ -433,9 +418,7 @@ bool LCodeGen::GenerateJumpTable() { __ ret(0); // Call the continuation without clobbering registers. } } else { - if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { - RestoreCallerDoubles(); - } + if (info()->saves_caller_doubles()) RestoreCallerDoubles(); __ call(entry, RelocInfo::RUNTIME_ENTRY); } } @@ -444,12 +427,10 @@ bool LCodeGen::GenerateJumpTable() { bool LCodeGen::GenerateDeferredCode() { - ASSERT(is_generating()); + DCHECK(is_generating()); if (deferred_.length() > 0) { for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { LDeferredCode* code = deferred_[i]; - X87Stack copy(code->x87_stack()); - x87_stack_ = copy; HValue* value = instructions_->at(code->instruction_index())->hydrogen_value(); @@ -464,8 +445,8 @@ bool LCodeGen::GenerateDeferredCode() { __ bind(code->entry()); if (NeedsDeferredFrame()) { Comment(";;; Build frame"); - ASSERT(!frame_is_built_); - ASSERT(info()->IsStub()); + DCHECK(!frame_is_built_); + DCHECK(info()->IsStub()); frame_is_built_ = true; // Build the frame in such a way that esi isn't trashed. __ push(ebp); // Caller's frame pointer. @@ -478,7 +459,7 @@ bool LCodeGen::GenerateDeferredCode() { if (NeedsDeferredFrame()) { __ bind(code->done()); Comment(";;; Destroy frame"); - ASSERT(frame_is_built_); + DCHECK(frame_is_built_); frame_is_built_ = false; __ mov(esp, ebp); __ pop(ebp); @@ -495,7 +476,7 @@ bool LCodeGen::GenerateDeferredCode() { bool LCodeGen::GenerateSafepointTable() { - ASSERT(is_done()); + DCHECK(is_done()); if (!info()->IsStub()) { // For lazy deoptimization we need space to patch a call after every call. // Ensure there is always space for such patching, even if the code ends @@ -515,234 +496,19 @@ Register LCodeGen::ToRegister(int index) const { } -X87Register LCodeGen::ToX87Register(int index) const { - return X87Register::FromAllocationIndex(index); -} - - XMMRegister LCodeGen::ToDoubleRegister(int index) const { return XMMRegister::FromAllocationIndex(index); } -void LCodeGen::X87LoadForUsage(X87Register reg) { - ASSERT(x87_stack_.Contains(reg)); - x87_stack_.Fxch(reg); - x87_stack_.pop(); -} - - -void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) { - ASSERT(x87_stack_.Contains(reg1)); - ASSERT(x87_stack_.Contains(reg2)); - x87_stack_.Fxch(reg1, 1); - x87_stack_.Fxch(reg2); - x87_stack_.pop(); - x87_stack_.pop(); -} - - -void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) { - ASSERT(is_mutable_); - ASSERT(Contains(reg) && stack_depth_ > other_slot); - int i = ArrayIndex(reg); - int st = st2idx(i); - if (st != other_slot) { - int other_i = st2idx(other_slot); - X87Register other = stack_[other_i]; - stack_[other_i] = reg; - stack_[i] = other; - if (st == 0) { - __ fxch(other_slot); - } else if (other_slot == 0) { - __ fxch(st); - } else { - __ fxch(st); - __ fxch(other_slot); - __ fxch(st); - } - } -} - - -int LCodeGen::X87Stack::st2idx(int pos) { - return stack_depth_ - pos - 1; -} - - -int LCodeGen::X87Stack::ArrayIndex(X87Register reg) { - for (int i = 0; i < stack_depth_; i++) { - if (stack_[i].is(reg)) return i; - } - UNREACHABLE(); - return -1; -} - - -bool LCodeGen::X87Stack::Contains(X87Register reg) { - for (int i = 0; i < stack_depth_; i++) { - if (stack_[i].is(reg)) return true; - } - return false; -} - - -void LCodeGen::X87Stack::Free(X87Register reg) { - ASSERT(is_mutable_); - ASSERT(Contains(reg)); - int i = ArrayIndex(reg); - int st = st2idx(i); - if (st > 0) { - // keep track of how fstp(i) changes the order of elements - int tos_i = st2idx(0); - stack_[i] = stack_[tos_i]; - } - pop(); - __ fstp(st); -} - - -void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) { - if (x87_stack_.Contains(dst)) { - x87_stack_.Fxch(dst); - __ fstp(0); - } else { - x87_stack_.push(dst); - } - X87Fld(src, opts); -} - - -void LCodeGen::X87Fld(Operand src, X87OperandType opts) { - ASSERT(!src.is_reg_only()); - switch (opts) { - case kX87DoubleOperand: - __ fld_d(src); - break; - case kX87FloatOperand: - __ fld_s(src); - break; - case kX87IntOperand: - __ fild_s(src); - break; - default: - UNREACHABLE(); - } -} - - -void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) { - ASSERT(!dst.is_reg_only()); - x87_stack_.Fxch(src); - switch (opts) { - case kX87DoubleOperand: - __ fst_d(dst); - break; - case kX87IntOperand: - __ fist_s(dst); - break; - default: - UNREACHABLE(); - } -} - - -void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) { - ASSERT(is_mutable_); - if (Contains(reg)) { - Free(reg); - } - // Mark this register as the next register to write to - stack_[stack_depth_] = reg; -} - - -void LCodeGen::X87Stack::CommitWrite(X87Register reg) { - ASSERT(is_mutable_); - // Assert the reg is prepared to write, but not on the virtual stack yet - ASSERT(!Contains(reg) && stack_[stack_depth_].is(reg) && - stack_depth_ < X87Register::kNumAllocatableRegisters); - stack_depth_++; -} - - -void LCodeGen::X87PrepareBinaryOp( - X87Register left, X87Register right, X87Register result) { - // You need to use DefineSameAsFirst for x87 instructions - ASSERT(result.is(left)); - x87_stack_.Fxch(right, 1); - x87_stack_.Fxch(left); -} - - -void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) { - if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters(isolate())) { - bool double_inputs = instr->HasDoubleRegisterInput(); - - // Flush stack from tos down, since FreeX87() will mess with tos - for (int i = stack_depth_-1; i >= 0; i--) { - X87Register reg = stack_[i]; - // Skip registers which contain the inputs for the next instruction - // when flushing the stack - if (double_inputs && instr->IsDoubleInput(reg, cgen)) { - continue; - } - Free(reg); - if (i < stack_depth_-1) i++; - } - } - if (instr->IsReturn()) { - while (stack_depth_ > 0) { - __ fstp(0); - stack_depth_--; - } - if (FLAG_debug_code && FLAG_enable_slow_asserts) __ VerifyX87StackDepth(0); - } -} - - -void LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr) { - ASSERT(stack_depth_ <= 1); - // If ever used for new stubs producing two pairs of doubles joined into two - // phis this assert hits. That situation is not handled, since the two stacks - // might have st0 and st1 swapped. - if (current_block_id + 1 != goto_instr->block_id()) { - // If we have a value on the x87 stack on leaving a block, it must be a - // phi input. If the next block we compile is not the join block, we have - // to discard the stack state. - stack_depth_ = 0; - } -} - - -void LCodeGen::EmitFlushX87ForDeopt() { - // The deoptimizer does not support X87 Registers. But as long as we - // deopt from a stub its not a problem, since we will re-materialize the - // original stub inputs, which can't be double registers. - ASSERT(info()->IsStub()); - if (FLAG_debug_code && FLAG_enable_slow_asserts) { - __ pushfd(); - __ VerifyX87StackDepth(x87_stack_.depth()); - __ popfd(); - } - for (int i = 0; i < x87_stack_.depth(); i++) __ fstp(0); -} - - Register LCodeGen::ToRegister(LOperand* op) const { - ASSERT(op->IsRegister()); + DCHECK(op->IsRegister()); return ToRegister(op->index()); } -X87Register LCodeGen::ToX87Register(LOperand* op) const { - ASSERT(op->IsDoubleRegister()); - return ToX87Register(op->index()); -} - - XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { - ASSERT(op->IsDoubleRegister()); + DCHECK(op->IsDoubleRegister()); return ToDoubleRegister(op->index()); } @@ -757,28 +523,28 @@ int32_t LCodeGen::ToRepresentation(LConstantOperand* op, HConstant* constant = chunk_->LookupConstant(op); int32_t value = constant->Integer32Value(); if (r.IsInteger32()) return value; - ASSERT(r.IsSmiOrTagged()); + DCHECK(r.IsSmiOrTagged()); return reinterpret_cast<int32_t>(Smi::FromInt(value)); } Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { HConstant* constant = chunk_->LookupConstant(op); - ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); + DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); return constant->handle(isolate()); } double LCodeGen::ToDouble(LConstantOperand* op) const { HConstant* constant = chunk_->LookupConstant(op); - ASSERT(constant->HasDoubleValue()); + DCHECK(constant->HasDoubleValue()); return constant->DoubleValue(); } ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const { HConstant* constant = chunk_->LookupConstant(op); - ASSERT(constant->HasExternalReferenceValue()); + DCHECK(constant->HasExternalReferenceValue()); return constant->ExternalReferenceValue(); } @@ -794,7 +560,7 @@ bool LCodeGen::IsSmi(LConstantOperand* op) const { static int ArgumentsOffsetWithoutFrame(int index) { - ASSERT(index < 0); + DCHECK(index < 0); return -(index + 1) * kPointerSize + kPCOnStackSize; } @@ -802,7 +568,7 @@ static int ArgumentsOffsetWithoutFrame(int index) { Operand LCodeGen::ToOperand(LOperand* op) const { if (op->IsRegister()) return Operand(ToRegister(op)); if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op)); - ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); + DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); if (NeedsEagerFrame()) { return Operand(ebp, StackSlotOffset(op->index())); } else { @@ -814,7 +580,7 @@ Operand LCodeGen::ToOperand(LOperand* op) const { Operand LCodeGen::HighOperand(LOperand* op) { - ASSERT(op->IsDoubleStackSlot()); + DCHECK(op->IsDoubleStackSlot()); if (NeedsEagerFrame()) { return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize); } else { @@ -849,13 +615,13 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, translation->BeginConstructStubFrame(closure_id, translation_size); break; case JS_GETTER: - ASSERT(translation_size == 1); - ASSERT(height == 0); + DCHECK(translation_size == 1); + DCHECK(height == 0); translation->BeginGetterStubFrame(closure_id); break; case JS_SETTER: - ASSERT(translation_size == 2); - ASSERT(height == 0); + DCHECK(translation_size == 2); + DCHECK(height == 0); translation->BeginSetterStubFrame(closure_id); break; case ARGUMENTS_ADAPTOR: @@ -955,7 +721,7 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr, SafepointMode safepoint_mode) { - ASSERT(instr != NULL); + DCHECK(instr != NULL); __ call(code, mode); RecordSafepointWithLazyDeopt(instr, safepoint_mode); @@ -979,14 +745,14 @@ void LCodeGen::CallRuntime(const Runtime::Function* fun, int argc, LInstruction* instr, SaveFPRegsMode save_doubles) { - ASSERT(instr != NULL); - ASSERT(instr->HasPointerMap()); + DCHECK(instr != NULL); + DCHECK(instr->HasPointerMap()); __ CallRuntime(fun, argc, save_doubles); RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); - ASSERT(info()->is_calling()); + DCHECK(info()->is_calling()); } @@ -1016,7 +782,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, RecordSafepointWithRegisters( instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); - ASSERT(info()->is_calling()); + DCHECK(info()->is_calling()); } @@ -1061,9 +827,9 @@ void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment, Deoptimizer::BailoutType bailout_type) { RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); - ASSERT(environment->HasBeenRegistered()); + DCHECK(environment->HasBeenRegistered()); int id = environment->deoptimization_index(); - ASSERT(info()->IsOptimizing() || info()->IsStub()); + DCHECK(info()->IsOptimizing() || info()->IsStub()); Address entry = Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); if (entry == NULL) { @@ -1084,7 +850,7 @@ void LCodeGen::DeoptimizeIf(Condition cc, __ mov(Operand::StaticVariable(count), eax); __ pop(eax); __ popfd(); - ASSERT(frame_is_built_); + DCHECK(frame_is_built_); __ call(entry, RelocInfo::RUNTIME_ENTRY); __ bind(&no_deopt); __ mov(Operand::StaticVariable(count), eax); @@ -1092,17 +858,6 @@ void LCodeGen::DeoptimizeIf(Condition cc, __ popfd(); } - // Before Instructions which can deopt, we normally flush the x87 stack. But - // we can have inputs or outputs of the current instruction on the stack, - // thus we need to flush them here from the physical stack to leave it in a - // consistent state. - if (x87_stack_.depth() > 0) { - Label done; - if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); - EmitFlushX87ForDeopt(); - __ bind(&done); - } - if (info()->ShouldTrapOnDeopt()) { Label done; if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); @@ -1110,7 +865,7 @@ void LCodeGen::DeoptimizeIf(Condition cc, __ bind(&done); } - ASSERT(info()->IsStub() || frame_is_built_); + DCHECK(info()->IsStub() || frame_is_built_); if (cc == no_condition && frame_is_built_) { __ call(entry, RelocInfo::RUNTIME_ENTRY); } else { @@ -1147,7 +902,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { int length = deoptimizations_.length(); if (length == 0) return; Handle<DeoptimizationInputData> data = - DeoptimizationInputData::New(isolate(), length, TENURED); + DeoptimizationInputData::New(isolate(), length, 0, TENURED); Handle<ByteArray> translations = translations_.CreateByteArray(isolate()->factory()); @@ -1198,7 +953,7 @@ int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { - ASSERT(deoptimization_literals_.length() == 0); + DCHECK(deoptimization_literals_.length() == 0); const ZoneList<Handle<JSFunction> >* inlined_closures = chunk()->inlined_closures(); @@ -1218,7 +973,7 @@ void LCodeGen::RecordSafepointWithLazyDeopt( if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); } else { - ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); + DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kLazyDeopt); } @@ -1230,7 +985,7 @@ void LCodeGen::RecordSafepoint( Safepoint::Kind kind, int arguments, Safepoint::DeoptMode deopt_mode) { - ASSERT(kind == expected_safepoint_kind_); + DCHECK(kind == expected_safepoint_kind_); const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); Safepoint safepoint = safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode); @@ -1317,8 +1072,8 @@ void LCodeGen::DoParameter(LParameter* instr) { void LCodeGen::DoCallStub(LCallStub* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->result()).is(eax)); switch (instr->hydrogen()->major_key()) { case CodeStub::RegExpExec: { RegExpExecStub stub(isolate()); @@ -1349,7 +1104,7 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); - ASSERT(dividend.is(ToRegister(instr->result()))); + DCHECK(dividend.is(ToRegister(instr->result()))); // Theoretically, a variation of the branch-free code for integer division by // a power of 2 (calculating the remainder via an additional multiplication @@ -1382,7 +1137,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { void LCodeGen::DoModByConstI(LModByConstI* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(ToRegister(instr->result()).is(eax)); if (divisor == 0) { DeoptimizeIf(no_condition, instr->environment()); @@ -1410,12 +1165,12 @@ void LCodeGen::DoModI(LModI* instr) { HMod* hmod = instr->hydrogen(); Register left_reg = ToRegister(instr->left()); - ASSERT(left_reg.is(eax)); + DCHECK(left_reg.is(eax)); Register right_reg = ToRegister(instr->right()); - ASSERT(!right_reg.is(eax)); - ASSERT(!right_reg.is(edx)); + DCHECK(!right_reg.is(eax)); + DCHECK(!right_reg.is(edx)); Register result_reg = ToRegister(instr->result()); - ASSERT(result_reg.is(edx)); + DCHECK(result_reg.is(edx)); Label done; // Check for x % 0, idiv would signal a divide error. We have to @@ -1465,8 +1220,8 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); Register result = ToRegister(instr->result()); - ASSERT(divisor == kMinInt || IsPowerOf2(Abs(divisor))); - ASSERT(!result.is(dividend)); + DCHECK(divisor == kMinInt || IsPowerOf2(Abs(divisor))); + DCHECK(!result.is(dividend)); // Check for (0 / -x) that will produce negative zero. HDiv* hdiv = instr->hydrogen(); @@ -1502,7 +1257,7 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { void LCodeGen::DoDivByConstI(LDivByConstI* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); - ASSERT(ToRegister(instr->result()).is(edx)); + DCHECK(ToRegister(instr->result()).is(edx)); if (divisor == 0) { DeoptimizeIf(no_condition, instr->environment()); @@ -1534,11 +1289,11 @@ void LCodeGen::DoDivI(LDivI* instr) { Register dividend = ToRegister(instr->dividend()); Register divisor = ToRegister(instr->divisor()); Register remainder = ToRegister(instr->temp()); - ASSERT(dividend.is(eax)); - ASSERT(remainder.is(edx)); - ASSERT(ToRegister(instr->result()).is(eax)); - ASSERT(!divisor.is(eax)); - ASSERT(!divisor.is(edx)); + DCHECK(dividend.is(eax)); + DCHECK(remainder.is(edx)); + DCHECK(ToRegister(instr->result()).is(eax)); + DCHECK(!divisor.is(eax)); + DCHECK(!divisor.is(edx)); // Check for x / 0. if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { @@ -1581,7 +1336,7 @@ void LCodeGen::DoDivI(LDivI* instr) { void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); - ASSERT(dividend.is(ToRegister(instr->result()))); + DCHECK(dividend.is(ToRegister(instr->result()))); // If the divisor is positive, things are easy: There can be no deopts and we // can simply do an arithmetic right shift. @@ -1598,14 +1353,17 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { DeoptimizeIf(zero, instr->environment()); } - if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { - __ sar(dividend, shift); + // Dividing by -1 is basically negation, unless we overflow. + if (divisor == -1) { + if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { + DeoptimizeIf(overflow, instr->environment()); + } return; } - // Dividing by -1 is basically negation, unless we overflow. - if (divisor == -1) { - DeoptimizeIf(overflow, instr->environment()); + // If the negation could not overflow, simply shifting is OK. + if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { + __ sar(dividend, shift); return; } @@ -1622,7 +1380,7 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); - ASSERT(ToRegister(instr->result()).is(edx)); + DCHECK(ToRegister(instr->result()).is(edx)); if (divisor == 0) { DeoptimizeIf(no_condition, instr->environment()); @@ -1648,7 +1406,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { // In the general case we may need to adjust before and after the truncating // division to get a flooring division. Register temp = ToRegister(instr->temp3()); - ASSERT(!temp.is(dividend) && !temp.is(eax) && !temp.is(edx)); + DCHECK(!temp.is(dividend) && !temp.is(eax) && !temp.is(edx)); Label needs_adjustment, done; __ cmp(dividend, Immediate(0)); __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear); @@ -1671,11 +1429,11 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { Register divisor = ToRegister(instr->divisor()); Register remainder = ToRegister(instr->temp()); Register result = ToRegister(instr->result()); - ASSERT(dividend.is(eax)); - ASSERT(remainder.is(edx)); - ASSERT(result.is(eax)); - ASSERT(!divisor.is(eax)); - ASSERT(!divisor.is(edx)); + DCHECK(dividend.is(eax)); + DCHECK(remainder.is(edx)); + DCHECK(result.is(eax)); + DCHECK(!divisor.is(eax)); + DCHECK(!divisor.is(edx)); // Check for x / 0. if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { @@ -1805,8 +1563,8 @@ void LCodeGen::DoMulI(LMulI* instr) { void LCodeGen::DoBitI(LBitI* instr) { LOperand* left = instr->left(); LOperand* right = instr->right(); - ASSERT(left->Equals(instr->result())); - ASSERT(left->IsRegister()); + DCHECK(left->Equals(instr->result())); + DCHECK(left->IsRegister()); if (right->IsConstantOperand()) { int32_t right_operand = @@ -1852,10 +1610,10 @@ void LCodeGen::DoBitI(LBitI* instr) { void LCodeGen::DoShiftI(LShiftI* instr) { LOperand* left = instr->left(); LOperand* right = instr->right(); - ASSERT(left->Equals(instr->result())); - ASSERT(left->IsRegister()); + DCHECK(left->Equals(instr->result())); + DCHECK(left->IsRegister()); if (right->IsRegister()) { - ASSERT(ToRegister(right).is(ecx)); + DCHECK(ToRegister(right).is(ecx)); switch (instr->op()) { case Token::ROR: @@ -1900,11 +1658,11 @@ void LCodeGen::DoShiftI(LShiftI* instr) { } break; case Token::SHR: - if (shift_count == 0 && instr->can_deopt()) { + if (shift_count != 0) { + __ shr(ToRegister(left), shift_count); + } else if (instr->can_deopt()) { __ test(ToRegister(left), ToRegister(left)); DeoptimizeIf(sign, instr->environment()); - } else { - __ shr(ToRegister(left), shift_count); } break; case Token::SHL: @@ -1932,7 +1690,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) { void LCodeGen::DoSubI(LSubI* instr) { LOperand* left = instr->left(); LOperand* right = instr->right(); - ASSERT(left->Equals(instr->result())); + DCHECK(left->Equals(instr->result())); if (right->IsConstantOperand()) { __ sub(ToOperand(left), @@ -1961,43 +1719,34 @@ void LCodeGen::DoConstantD(LConstantD* instr) { uint64_t int_val = BitCast<uint64_t, double>(v); int32_t lower = static_cast<int32_t>(int_val); int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); - ASSERT(instr->result()->IsDoubleRegister()); - - if (!CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - __ push(Immediate(upper)); - __ push(Immediate(lower)); - X87Register reg = ToX87Register(instr->result()); - X87Mov(reg, Operand(esp, 0)); - __ add(Operand(esp), Immediate(kDoubleSize)); + DCHECK(instr->result()->IsDoubleRegister()); + + XMMRegister res = ToDoubleRegister(instr->result()); + if (int_val == 0) { + __ xorps(res, res); } else { - CpuFeatureScope scope1(masm(), SSE2); - XMMRegister res = ToDoubleRegister(instr->result()); - if (int_val == 0) { - __ xorps(res, res); - } else { - Register temp = ToRegister(instr->temp()); - if (CpuFeatures::IsSupported(SSE4_1)) { - CpuFeatureScope scope2(masm(), SSE4_1); - if (lower != 0) { - __ Move(temp, Immediate(lower)); - __ movd(res, Operand(temp)); - __ Move(temp, Immediate(upper)); - __ pinsrd(res, Operand(temp), 1); - } else { - __ xorps(res, res); - __ Move(temp, Immediate(upper)); - __ pinsrd(res, Operand(temp), 1); - } + Register temp = ToRegister(instr->temp()); + if (CpuFeatures::IsSupported(SSE4_1)) { + CpuFeatureScope scope2(masm(), SSE4_1); + if (lower != 0) { + __ Move(temp, Immediate(lower)); + __ movd(res, Operand(temp)); + __ Move(temp, Immediate(upper)); + __ pinsrd(res, Operand(temp), 1); } else { + __ xorps(res, res); __ Move(temp, Immediate(upper)); - __ movd(res, Operand(temp)); - __ psllq(res, 32); - if (lower != 0) { - XMMRegister xmm_scratch = double_scratch0(); - __ Move(temp, Immediate(lower)); - __ movd(xmm_scratch, Operand(temp)); - __ orps(res, xmm_scratch); - } + __ pinsrd(res, Operand(temp), 1); + } + } else { + __ Move(temp, Immediate(upper)); + __ movd(res, Operand(temp)); + __ psllq(res, 32); + if (lower != 0) { + XMMRegister xmm_scratch = double_scratch0(); + __ Move(temp, Immediate(lower)); + __ movd(xmm_scratch, Operand(temp)); + __ orps(res, xmm_scratch); } } } @@ -2013,13 +1762,6 @@ void LCodeGen::DoConstantT(LConstantT* instr) { Register reg = ToRegister(instr->result()); Handle<Object> object = instr->value(isolate()); AllowDeferredHandleDereference smi_check; - if (instr->hydrogen()->HasObjectMap()) { - Handle<Map> object_map = instr->hydrogen()->ObjectMap().handle(); - ASSERT(object->IsHeapObject()); - ASSERT(!object_map->is_stable() || - *object_map == Handle<HeapObject>::cast(object)->map()); - USE(object_map); - } __ LoadObject(reg, object); } @@ -2037,8 +1779,8 @@ void LCodeGen::DoDateField(LDateField* instr) { Register scratch = ToRegister(instr->temp()); Smi* index = instr->index(); Label runtime, done; - ASSERT(object.is(result)); - ASSERT(object.is(eax)); + DCHECK(object.is(result)); + DCHECK(object.is(eax)); __ test(object, Immediate(kSmiTagMask)); DeoptimizeIf(zero, instr->environment()); @@ -2133,12 +1875,12 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { if (instr->value()->IsConstantOperand()) { int value = ToRepresentation(LConstantOperand::cast(instr->value()), Representation::Integer32()); - ASSERT_LE(0, value); + DCHECK_LE(0, value); if (encoding == String::ONE_BYTE_ENCODING) { - ASSERT_LE(value, String::kMaxOneByteCharCode); + DCHECK_LE(value, String::kMaxOneByteCharCode); __ mov_b(operand, static_cast<int8_t>(value)); } else { - ASSERT_LE(value, String::kMaxUtf16CodeUnit); + DCHECK_LE(value, String::kMaxUtf16CodeUnit); __ mov_w(operand, static_cast<int16_t>(value)); } } else { @@ -2180,10 +1922,9 @@ void LCodeGen::DoAddI(LAddI* instr) { void LCodeGen::DoMathMinMax(LMathMinMax* instr) { - CpuFeatureScope scope(masm(), SSE2); LOperand* left = instr->left(); LOperand* right = instr->right(); - ASSERT(left->Equals(instr->result())); + DCHECK(left->Equals(instr->result())); HMathMinMax::Operation operation = instr->hydrogen()->operation(); if (instr->hydrogen()->representation().IsSmiOrInteger32()) { Label return_left; @@ -2206,7 +1947,7 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { } __ bind(&return_left); } else { - ASSERT(instr->hydrogen()->representation().IsDouble()); + DCHECK(instr->hydrogen()->representation().IsDouble()); Label check_nan_left, check_zero, return_left, return_right; Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; XMMRegister left_reg = ToDoubleRegister(left); @@ -2243,97 +1984,54 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { void LCodeGen::DoArithmeticD(LArithmeticD* instr) { - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister left = ToDoubleRegister(instr->left()); - XMMRegister right = ToDoubleRegister(instr->right()); - XMMRegister result = ToDoubleRegister(instr->result()); - switch (instr->op()) { - case Token::ADD: - __ addsd(left, right); - break; - case Token::SUB: - __ subsd(left, right); - break; - case Token::MUL: - __ mulsd(left, right); - break; - case Token::DIV: - __ divsd(left, right); - // Don't delete this mov. It may improve performance on some CPUs, - // when there is a mulsd depending on the result - __ movaps(left, left); - break; - case Token::MOD: { - // Pass two doubles as arguments on the stack. - __ PrepareCallCFunction(4, eax); - __ movsd(Operand(esp, 0 * kDoubleSize), left); - __ movsd(Operand(esp, 1 * kDoubleSize), right); - __ CallCFunction( - ExternalReference::mod_two_doubles_operation(isolate()), - 4); - - // Return value is in st(0) on ia32. - // Store it into the result register. - __ sub(Operand(esp), Immediate(kDoubleSize)); - __ fstp_d(Operand(esp, 0)); - __ movsd(result, Operand(esp, 0)); - __ add(Operand(esp), Immediate(kDoubleSize)); - break; - } - default: - UNREACHABLE(); - break; - } - } else { - X87Register left = ToX87Register(instr->left()); - X87Register right = ToX87Register(instr->right()); - X87Register result = ToX87Register(instr->result()); - if (instr->op() != Token::MOD) { - X87PrepareBinaryOp(left, right, result); - } - switch (instr->op()) { - case Token::ADD: - __ fadd_i(1); - break; - case Token::SUB: - __ fsub_i(1); - break; - case Token::MUL: - __ fmul_i(1); - break; - case Token::DIV: - __ fdiv_i(1); - break; - case Token::MOD: { - // Pass two doubles as arguments on the stack. - __ PrepareCallCFunction(4, eax); - X87Mov(Operand(esp, 1 * kDoubleSize), right); - X87Mov(Operand(esp, 0), left); - X87Free(right); - ASSERT(left.is(result)); - X87PrepareToWrite(result); - __ CallCFunction( - ExternalReference::mod_two_doubles_operation(isolate()), - 4); - - // Return value is in st(0) on ia32. - X87CommitWrite(result); - break; - } - default: - UNREACHABLE(); - break; + XMMRegister left = ToDoubleRegister(instr->left()); + XMMRegister right = ToDoubleRegister(instr->right()); + XMMRegister result = ToDoubleRegister(instr->result()); + switch (instr->op()) { + case Token::ADD: + __ addsd(left, right); + break; + case Token::SUB: + __ subsd(left, right); + break; + case Token::MUL: + __ mulsd(left, right); + break; + case Token::DIV: + __ divsd(left, right); + // Don't delete this mov. It may improve performance on some CPUs, + // when there is a mulsd depending on the result + __ movaps(left, left); + break; + case Token::MOD: { + // Pass two doubles as arguments on the stack. + __ PrepareCallCFunction(4, eax); + __ movsd(Operand(esp, 0 * kDoubleSize), left); + __ movsd(Operand(esp, 1 * kDoubleSize), right); + __ CallCFunction( + ExternalReference::mod_two_doubles_operation(isolate()), + 4); + + // Return value is in st(0) on ia32. + // Store it into the result register. + __ sub(Operand(esp), Immediate(kDoubleSize)); + __ fstp_d(Operand(esp, 0)); + __ movsd(result, Operand(esp, 0)); + __ add(Operand(esp), Immediate(kDoubleSize)); + break; } + default: + UNREACHABLE(); + break; } } void LCodeGen::DoArithmeticT(LArithmeticT* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->left()).is(edx)); - ASSERT(ToRegister(instr->right()).is(eax)); - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->left()).is(edx)); + DCHECK(ToRegister(instr->right()).is(eax)); + DCHECK(ToRegister(instr->result()).is(eax)); BinaryOpICStub stub(isolate(), instr->op(), NO_OVERWRITE); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); @@ -2378,37 +2076,35 @@ void LCodeGen::DoBranch(LBranch* instr) { __ test(reg, Operand(reg)); EmitBranch(instr, not_zero); } else if (r.IsDouble()) { - ASSERT(!info()->IsStub()); - CpuFeatureScope scope(masm(), SSE2); + DCHECK(!info()->IsStub()); XMMRegister reg = ToDoubleRegister(instr->value()); XMMRegister xmm_scratch = double_scratch0(); __ xorps(xmm_scratch, xmm_scratch); __ ucomisd(reg, xmm_scratch); EmitBranch(instr, not_equal); } else { - ASSERT(r.IsTagged()); + DCHECK(r.IsTagged()); Register reg = ToRegister(instr->value()); HType type = instr->hydrogen()->value()->type(); if (type.IsBoolean()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); __ cmp(reg, factory()->true_value()); EmitBranch(instr, equal); } else if (type.IsSmi()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); __ test(reg, Operand(reg)); EmitBranch(instr, not_equal); } else if (type.IsJSArray()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); EmitBranch(instr, no_condition); } else if (type.IsHeapNumber()) { - ASSERT(!info()->IsStub()); - CpuFeatureScope scope(masm(), SSE2); + DCHECK(!info()->IsStub()); XMMRegister xmm_scratch = double_scratch0(); __ xorps(xmm_scratch, xmm_scratch); __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); EmitBranch(instr, not_equal); } else if (type.IsString()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); EmitBranch(instr, not_equal); } else { @@ -2448,7 +2144,7 @@ void LCodeGen::DoBranch(LBranch* instr) { Register map = no_reg; // Keep the compiler happy. if (expected.NeedsMap()) { map = ToRegister(instr->temp()); - ASSERT(!map.is(reg)); + DCHECK(!map.is(reg)); __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); if (expected.CanBeUndetectable()) { @@ -2488,16 +2184,9 @@ void LCodeGen::DoBranch(LBranch* instr) { __ cmp(FieldOperand(reg, HeapObject::kMapOffset), factory()->heap_number_map()); __ j(not_equal, ¬_heap_number, Label::kNear); - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister xmm_scratch = double_scratch0(); - __ xorps(xmm_scratch, xmm_scratch); - __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); - } else { - __ fldz(); - __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); - __ FCmp(); - } + XMMRegister xmm_scratch = double_scratch0(); + __ xorps(xmm_scratch, xmm_scratch); + __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); __ j(zero, instr->FalseLabel(chunk_)); __ jmp(instr->TrueLabel(chunk_)); __ bind(¬_heap_number); @@ -2520,10 +2209,6 @@ void LCodeGen::EmitGoto(int block) { } -void LCodeGen::DoClobberDoubles(LClobberDoubles* instr) { -} - - void LCodeGen::DoGoto(LGoto* instr) { EmitGoto(instr->block_id()); } @@ -2564,7 +2249,11 @@ Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { LOperand* left = instr->left(); LOperand* right = instr->right(); - Condition cc = TokenToCondition(instr->op(), instr->is_double()); + bool is_unsigned = + instr->is_double() || + instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) || + instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32); + Condition cc = TokenToCondition(instr->op(), is_unsigned); if (left->IsConstantOperand() && right->IsConstantOperand()) { // We can statically evaluate the comparison. @@ -2575,13 +2264,7 @@ void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { EmitGoto(next_block); } else { if (instr->is_double()) { - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); - } else { - X87LoadForUsage(ToX87Register(right), ToX87Register(left)); - __ FCmp(); - } + __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); // Don't base result on EFLAGS when a NaN is involved. Instead // jump to the false block. __ j(parity_even, instr->FalseLabel(chunk_)); @@ -2592,8 +2275,8 @@ void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { } else if (left->IsConstantOperand()) { __ cmp(ToOperand(right), ToImmediate(left, instr->hydrogen()->representation())); - // We transposed the operands. Reverse the condition. - cc = ReverseCondition(cc); + // We commuted the operands, so commute the condition. + cc = CommuteCondition(cc); } else { __ cmp(ToRegister(left), ToOperand(right)); } @@ -2625,35 +2308,12 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { return; } - bool use_sse2 = CpuFeatures::IsSupported(SSE2); - if (use_sse2) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister input_reg = ToDoubleRegister(instr->object()); - __ ucomisd(input_reg, input_reg); - EmitFalseBranch(instr, parity_odd); - } else { - // Put the value to the top of stack - X87Register src = ToX87Register(instr->object()); - X87LoadForUsage(src); - __ fld(0); - __ fld(0); - __ FCmp(); - Label ok; - __ j(parity_even, &ok, Label::kNear); - __ fstp(0); - EmitFalseBranch(instr, no_condition); - __ bind(&ok); - } - + XMMRegister input_reg = ToDoubleRegister(instr->object()); + __ ucomisd(input_reg, input_reg); + EmitFalseBranch(instr, parity_odd); __ sub(esp, Immediate(kDoubleSize)); - if (use_sse2) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister input_reg = ToDoubleRegister(instr->object()); - __ movsd(MemOperand(esp, 0), input_reg); - } else { - __ fstp_d(MemOperand(esp, 0)); - } + __ movsd(MemOperand(esp, 0), input_reg); __ add(esp, Immediate(kDoubleSize)); int offset = sizeof(kHoleNanUpper32); @@ -2664,11 +2324,10 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { Representation rep = instr->hydrogen()->value()->representation(); - ASSERT(!rep.IsInteger32()); + DCHECK(!rep.IsInteger32()); Register scratch = ToRegister(instr->temp()); if (rep.IsDouble()) { - CpuFeatureScope use_sse2(masm(), SSE2); XMMRegister value = ToDoubleRegister(instr->value()); XMMRegister xmm_scratch = double_scratch0(); __ xorps(xmm_scratch, xmm_scratch); @@ -2744,7 +2403,7 @@ void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { Register temp = ToRegister(instr->temp()); SmiCheck check_needed = - instr->hydrogen()->value()->IsHeapObject() + instr->hydrogen()->value()->type().IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; Condition true_cond = EmitIsString( @@ -2766,7 +2425,7 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { Register input = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - if (!instr->hydrogen()->value()->IsHeapObject()) { + if (!instr->hydrogen()->value()->type().IsHeapObject()) { STATIC_ASSERT(kSmiTag == 0); __ JumpIfSmi(input, instr->FalseLabel(chunk_)); } @@ -2814,7 +2473,7 @@ static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { InstanceType from = instr->from(); InstanceType to = instr->to(); if (from == FIRST_TYPE) return to; - ASSERT(from == to || to == LAST_TYPE); + DCHECK(from == to || to == LAST_TYPE); return from; } @@ -2834,7 +2493,7 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { Register input = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - if (!instr->hydrogen()->value()->IsHeapObject()) { + if (!instr->hydrogen()->value()->type().IsHeapObject()) { __ JumpIfSmi(input, instr->FalseLabel(chunk_)); } @@ -2872,9 +2531,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true, Register input, Register temp, Register temp2) { - ASSERT(!input.is(temp)); - ASSERT(!input.is(temp2)); - ASSERT(!temp.is(temp2)); + DCHECK(!input.is(temp)); + DCHECK(!input.is(temp2)); + DCHECK(!temp.is(temp2)); __ JumpIfSmi(input, is_false); if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Function"))) { @@ -2952,7 +2611,7 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { void LCodeGen::DoInstanceOf(LInstanceOf* instr) { // Object and function are in fixed registers defined by the stub. - ASSERT(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->context()).is(esi)); InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); @@ -2971,9 +2630,8 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode { public: DeferredInstanceOfKnownGlobal(LCodeGen* codegen, - LInstanceOfKnownGlobal* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + LInstanceOfKnownGlobal* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); } @@ -2985,7 +2643,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { }; DeferredInstanceOfKnownGlobal* deferred; - deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_); + deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); Label done, false_result; Register object = ToRegister(instr->value()); @@ -3049,7 +2707,7 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, // stack is used to pass the offset to the location of the map check to // the stub. Register temp = ToRegister(instr->temp()); - ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); + DCHECK(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); __ LoadHeapObject(InstanceofStub::right(), instr->function()); static const int kAdditionalDelta = 13; int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; @@ -3105,7 +2763,7 @@ void LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) { __ SmiUntag(reg); Register return_addr_reg = reg.is(ecx) ? ebx : ecx; if (dynamic_frame_alignment && FLAG_debug_code) { - ASSERT(extra_value_count == 2); + DCHECK(extra_value_count == 2); __ cmp(Operand(esp, reg, times_pointer_size, extra_value_count * kPointerSize), Immediate(kAlignmentZapValue)); @@ -3134,9 +2792,7 @@ void LCodeGen::DoReturn(LReturn* instr) { __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ CallRuntime(Runtime::kTraceExit, 1); } - if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { - RestoreCallerDoubles(); - } + if (info()->saves_caller_doubles()) RestoreCallerDoubles(); if (dynamic_frame_alignment_) { // Fetch the state of the dynamic frame alignment. __ mov(edx, Operand(ebp, @@ -3175,11 +2831,20 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->global_object()).is(edx)); - ASSERT(ToRegister(instr->result()).is(eax)); - - __ mov(ecx, instr->name()); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister())); + DCHECK(ToRegister(instr->result()).is(eax)); + + __ mov(LoadIC::NameRegister(), instr->name()); + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + DCHECK(vector.is(LoadIC::VectorRegister())); + __ mov(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + DCHECK(LoadIC::SlotRegister().is(eax)); + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(instr->hydrogen()->slot()))); + } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); CallCode(ic, RelocInfo::CODE_TARGET, instr); @@ -3243,7 +2908,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { __ mov(target, value); if (instr->hydrogen()->NeedsWriteBarrier()) { SmiCheck check_needed = - instr->hydrogen()->value()->IsHeapObject() + instr->hydrogen()->value()->type().IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; Register temp = ToRegister(instr->temp()); int offset = Context::SlotOffset(instr->slot_index()); @@ -3251,7 +2916,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { offset, value, temp, - GetSaveFPRegsMode(isolate()), + kSaveFPRegs, EMIT_REMEMBERED_SET, check_needed); } @@ -3276,13 +2941,8 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { Register object = ToRegister(instr->object()); if (instr->hydrogen()->representation().IsDouble()) { - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister result = ToDoubleRegister(instr->result()); - __ movsd(result, FieldOperand(object, offset)); - } else { - X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); - } + XMMRegister result = ToDoubleRegister(instr->result()); + __ movsd(result, FieldOperand(object, offset)); return; } @@ -3296,7 +2956,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { - ASSERT(!operand->IsDoubleRegister()); + DCHECK(!operand->IsDoubleRegister()); if (operand->IsConstantOperand()) { Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); AllowDeferredHandleDereference smi_check; @@ -3314,11 +2974,20 @@ void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->object()).is(edx)); - ASSERT(ToRegister(instr->result()).is(eax)); - - __ mov(ecx, instr->name()); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); + DCHECK(ToRegister(instr->result()).is(eax)); + + __ mov(LoadIC::NameRegister(), instr->name()); + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + DCHECK(vector.is(LoadIC::VectorRegister())); + __ mov(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + DCHECK(LoadIC::SlotRegister().is(eax)); + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(instr->hydrogen()->slot()))); + } Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3329,16 +2998,6 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { Register temp = ToRegister(instr->temp()); Register result = ToRegister(instr->result()); - // Check that the function really is a function. - __ CmpObjectType(function, JS_FUNCTION_TYPE, result); - DeoptimizeIf(not_equal, instr->environment()); - - // Check whether the function has an instance prototype. - Label non_instance; - __ test_b(FieldOperand(result, Map::kBitFieldOffset), - 1 << Map::kHasNonInstancePrototype); - __ j(not_zero, &non_instance, Label::kNear); - // Get the prototype or initial map from the function. __ mov(result, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); @@ -3354,12 +3013,6 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { // Get the prototype from the initial map. __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); - __ jmp(&done, Label::kNear); - - // Non-instance prototype: Fetch prototype from constructor field - // in the function's map. - __ bind(&non_instance); - __ mov(result, FieldOperand(result, Map::kConstructorOffset)); // All done. __ bind(&done); @@ -3405,26 +3058,15 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { key, instr->hydrogen()->key()->representation(), elements_kind, - 0, - instr->additional_index())); + instr->base_offset())); if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || elements_kind == FLOAT32_ELEMENTS) { - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister result(ToDoubleRegister(instr->result())); - __ movss(result, operand); - __ cvtss2sd(result, result); - } else { - X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); - } + XMMRegister result(ToDoubleRegister(instr->result())); + __ movss(result, operand); + __ cvtss2sd(result, result); } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) { - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - __ movsd(ToDoubleRegister(instr->result()), operand); - } else { - X87Mov(ToX87Register(instr->result()), operand); - } + __ movsd(ToDoubleRegister(instr->result()), operand); } else { Register result(ToRegister(instr->result())); switch (elements_kind) { @@ -3479,14 +3121,11 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { if (instr->hydrogen()->RequiresHoleCheck()) { - int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + - sizeof(kHoleNanLower32); Operand hole_check_operand = BuildFastArrayOperand( instr->elements(), instr->key(), instr->hydrogen()->key()->representation(), FAST_DOUBLE_ELEMENTS, - offset, - instr->additional_index()); + instr->base_offset() + sizeof(kHoleNanLower32)); __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); DeoptimizeIf(equal, instr->environment()); } @@ -3496,15 +3135,9 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { instr->key(), instr->hydrogen()->key()->representation(), FAST_DOUBLE_ELEMENTS, - FixedDoubleArray::kHeaderSize - kHeapObjectTag, - instr->additional_index()); - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister result = ToDoubleRegister(instr->result()); - __ movsd(result, double_load_operand); - } else { - X87Mov(ToX87Register(instr->result()), double_load_operand); - } + instr->base_offset()); + XMMRegister result = ToDoubleRegister(instr->result()); + __ movsd(result, double_load_operand); } @@ -3517,8 +3150,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { instr->key(), instr->hydrogen()->key()->representation(), FAST_ELEMENTS, - FixedArray::kHeaderSize - kHeapObjectTag, - instr->additional_index())); + instr->base_offset())); // Check for the hole value. if (instr->hydrogen()->RequiresHoleCheck()) { @@ -3549,13 +3181,9 @@ Operand LCodeGen::BuildFastArrayOperand( LOperand* key, Representation key_representation, ElementsKind elements_kind, - uint32_t offset, - uint32_t additional_index) { + uint32_t base_offset) { Register elements_pointer_reg = ToRegister(elements_pointer); int element_shift_size = ElementsKindToShiftSize(elements_kind); - if (IsFixedTypedArrayElementsKind(elements_kind)) { - offset += FixedTypedArrayBase::kDataOffset - kHeapObjectTag; - } int shift_size = element_shift_size; if (key->IsConstantOperand()) { int constant_value = ToInteger32(LConstantOperand::cast(key)); @@ -3563,8 +3191,8 @@ Operand LCodeGen::BuildFastArrayOperand( Abort(kArrayIndexConstantValueTooBig); } return Operand(elements_pointer_reg, - ((constant_value + additional_index) << shift_size) - + offset); + ((constant_value) << shift_size) + + base_offset); } else { // Take the tag bit into account while computing the shift size. if (key_representation.IsSmi() && (shift_size >= 1)) { @@ -3574,15 +3202,25 @@ Operand LCodeGen::BuildFastArrayOperand( return Operand(elements_pointer_reg, ToRegister(key), scale_factor, - offset + (additional_index << element_shift_size)); + base_offset); } } void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->object()).is(edx)); - ASSERT(ToRegister(instr->key()).is(ecx)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); + DCHECK(ToRegister(instr->key()).is(LoadIC::NameRegister())); + + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + DCHECK(vector.is(LoadIC::VectorRegister())); + __ mov(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + DCHECK(LoadIC::SlotRegister().is(eax)); + __ mov(LoadIC::SlotRegister(), + Immediate(Smi::FromInt(instr->hydrogen()->slot()))); + } Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); CallCode(ic, RelocInfo::CODE_TARGET, instr); @@ -3683,8 +3321,8 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); __ mov(receiver, Operand(receiver, global_offset)); - const int receiver_offset = GlobalObject::kGlobalReceiverOffset; - __ mov(receiver, FieldOperand(receiver, receiver_offset)); + const int proxy_offset = GlobalObject::kGlobalProxyOffset; + __ mov(receiver, FieldOperand(receiver, proxy_offset)); __ bind(&receiver_ok); } @@ -3694,9 +3332,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { Register function = ToRegister(instr->function()); Register length = ToRegister(instr->length()); Register elements = ToRegister(instr->elements()); - ASSERT(receiver.is(eax)); // Used for parameter count. - ASSERT(function.is(edi)); // Required by InvokeFunction. - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(receiver.is(eax)); // Used for parameter count. + DCHECK(function.is(edi)); // Required by InvokeFunction. + DCHECK(ToRegister(instr->result()).is(eax)); // Copy the arguments to this function possibly from the // adaptor frame below it. @@ -3720,7 +3358,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { // Invoke the function. __ bind(&invoke); - ASSERT(instr->HasPointerMap()); + DCHECK(instr->HasPointerMap()); LPointerMap* pointers = instr->pointer_map(); SafepointGenerator safepoint_generator( this, pointers, Safepoint::kLazyDeopt); @@ -3757,17 +3395,17 @@ void LCodeGen::DoContext(LContext* instr) { __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); } else { // If there is no frame, the context must be in esi. - ASSERT(result.is(esi)); + DCHECK(result.is(esi)); } } void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->context()).is(esi)); __ push(esi); // The context is the first argument. __ push(Immediate(instr->hydrogen()->pairs())); __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); - CallRuntime(Runtime::kHiddenDeclareGlobals, 3, instr); + CallRuntime(Runtime::kDeclareGlobals, 3, instr); } @@ -3815,7 +3453,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(ToRegister(instr->result()).is(eax)); LPointerMap* pointers = instr->pointer_map(); SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); @@ -3826,7 +3464,7 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); __ call(code, RelocInfo::CODE_TARGET); } else { - ASSERT(instr->target()->IsRegister()); + DCHECK(instr->target()->IsRegister()); Register target = ToRegister(instr->target()); generator.BeforeCall(__ CallSize(Operand(target))); __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag)); @@ -3837,8 +3475,8 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { - ASSERT(ToRegister(instr->function()).is(edi)); - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(ToRegister(instr->function()).is(edi)); + DCHECK(ToRegister(instr->result()).is(eax)); if (instr->hydrogen()->pass_argument_count()) { __ mov(eax, instr->arity()); @@ -3891,7 +3529,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { // Slow case: Call the runtime system to do the number allocation. __ bind(&slow); - CallRuntimeFromDeferred(Runtime::kHiddenAllocateHeapNumber, 0, + CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr, instr->context()); // Set the pointer to the new heap number in tmp. if (!tmp.is(eax)) __ mov(tmp, eax); @@ -3926,9 +3564,8 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode { public: DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, - LMathAbs* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + LMathAbs* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); } @@ -3937,10 +3574,9 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { LMathAbs* instr_; }; - ASSERT(instr->value()->Equals(instr->result())); + DCHECK(instr->value()->Equals(instr->result())); Representation r = instr->hydrogen()->value()->representation(); - CpuFeatureScope scope(masm(), SSE2); if (r.IsDouble()) { XMMRegister scratch = double_scratch0(); XMMRegister input_reg = ToDoubleRegister(instr->value()); @@ -3951,7 +3587,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { EmitIntegerMathAbs(instr); } else { // Tagged case. DeferredMathAbsTaggedHeapNumber* deferred = - new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_); + new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); Register input_reg = ToRegister(instr->value()); // Smi check. __ JumpIfNotSmi(input_reg, deferred->entry()); @@ -3962,7 +3598,6 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { void LCodeGen::DoMathFloor(LMathFloor* instr) { - CpuFeatureScope scope(masm(), SSE2); XMMRegister xmm_scratch = double_scratch0(); Register output_reg = ToRegister(instr->result()); XMMRegister input_reg = ToDoubleRegister(instr->value()); @@ -4028,7 +3663,6 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { void LCodeGen::DoMathRound(LMathRound* instr) { - CpuFeatureScope scope(masm(), SSE2); Register output_reg = ToRegister(instr->result()); XMMRegister input_reg = ToDoubleRegister(instr->value()); XMMRegister xmm_scratch = double_scratch0(); @@ -4090,20 +3724,26 @@ void LCodeGen::DoMathRound(LMathRound* instr) { } -void LCodeGen::DoMathSqrt(LMathSqrt* instr) { - CpuFeatureScope scope(masm(), SSE2); +void LCodeGen::DoMathFround(LMathFround* instr) { XMMRegister input_reg = ToDoubleRegister(instr->value()); - ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); - __ sqrtsd(input_reg, input_reg); + XMMRegister output_reg = ToDoubleRegister(instr->result()); + __ cvtsd2ss(output_reg, input_reg); + __ cvtss2sd(output_reg, output_reg); +} + + +void LCodeGen::DoMathSqrt(LMathSqrt* instr) { + Operand input = ToOperand(instr->value()); + XMMRegister output = ToDoubleRegister(instr->result()); + __ sqrtsd(output, input); } void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { - CpuFeatureScope scope(masm(), SSE2); XMMRegister xmm_scratch = double_scratch0(); XMMRegister input_reg = ToDoubleRegister(instr->value()); Register scratch = ToRegister(instr->temp()); - ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); + DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); // Note that according to ECMA-262 15.8.2.13: // Math.pow(-Infinity, 0.5) == Infinity @@ -4137,12 +3777,12 @@ void LCodeGen::DoPower(LPower* instr) { Representation exponent_type = instr->hydrogen()->right()->representation(); // Having marked this as a call, we can use any registers. // Just make sure that the input/output registers are the expected ones. - ASSERT(!instr->right()->IsDoubleRegister() || + DCHECK(!instr->right()->IsDoubleRegister() || ToDoubleRegister(instr->right()).is(xmm1)); - ASSERT(!instr->right()->IsRegister() || + DCHECK(!instr->right()->IsRegister() || ToRegister(instr->right()).is(eax)); - ASSERT(ToDoubleRegister(instr->left()).is(xmm2)); - ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); + DCHECK(ToDoubleRegister(instr->left()).is(xmm2)); + DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); if (exponent_type.IsSmi()) { MathPowStub stub(isolate(), MathPowStub::TAGGED); @@ -4159,7 +3799,7 @@ void LCodeGen::DoPower(LPower* instr) { MathPowStub stub(isolate(), MathPowStub::INTEGER); __ CallStub(&stub); } else { - ASSERT(exponent_type.IsDouble()); + DCHECK(exponent_type.IsDouble()); MathPowStub stub(isolate(), MathPowStub::DOUBLE); __ CallStub(&stub); } @@ -4167,8 +3807,7 @@ void LCodeGen::DoPower(LPower* instr) { void LCodeGen::DoMathLog(LMathLog* instr) { - CpuFeatureScope scope(masm(), SSE2); - ASSERT(instr->value()->Equals(instr->result())); + DCHECK(instr->value()->Equals(instr->result())); XMMRegister input_reg = ToDoubleRegister(instr->value()); XMMRegister xmm_scratch = double_scratch0(); Label positive, done, zero; @@ -4199,7 +3838,6 @@ void LCodeGen::DoMathLog(LMathLog* instr) { void LCodeGen::DoMathClz32(LMathClz32* instr) { - CpuFeatureScope scope(masm(), SSE2); Register input = ToRegister(instr->value()); Register result = ToRegister(instr->result()); Label not_zero_input; @@ -4214,7 +3852,6 @@ void LCodeGen::DoMathClz32(LMathClz32* instr) { void LCodeGen::DoMathExp(LMathExp* instr) { - CpuFeatureScope scope(masm(), SSE2); XMMRegister input = ToDoubleRegister(instr->value()); XMMRegister result = ToDoubleRegister(instr->result()); XMMRegister temp0 = double_scratch0(); @@ -4226,9 +3863,9 @@ void LCodeGen::DoMathExp(LMathExp* instr) { void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->function()).is(edi)); - ASSERT(instr->HasPointerMap()); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->function()).is(edi)); + DCHECK(instr->HasPointerMap()); Handle<JSFunction> known_function = instr->hydrogen()->known_function(); if (known_function.is_null()) { @@ -4248,9 +3885,9 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { void LCodeGen::DoCallFunction(LCallFunction* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->function()).is(edi)); - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->function()).is(edi)); + DCHECK(ToRegister(instr->result()).is(eax)); int arity = instr->arity(); CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); @@ -4259,9 +3896,9 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { void LCodeGen::DoCallNew(LCallNew* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->constructor()).is(edi)); - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->constructor()).is(edi)); + DCHECK(ToRegister(instr->result()).is(eax)); // No cell in ebx for construct type feedback in optimized code __ mov(ebx, isolate()->factory()->undefined_value()); @@ -4272,9 +3909,9 @@ void LCodeGen::DoCallNew(LCallNew* instr) { void LCodeGen::DoCallNewArray(LCallNewArray* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->constructor()).is(edi)); - ASSERT(ToRegister(instr->result()).is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->constructor()).is(edi)); + DCHECK(ToRegister(instr->result()).is(eax)); __ Move(eax, Immediate(instr->arity())); __ mov(ebx, isolate()->factory()->undefined_value()); @@ -4317,7 +3954,7 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { void LCodeGen::DoCallRuntime(LCallRuntime* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->context()).is(esi)); CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); } @@ -4350,7 +3987,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { int offset = access.offset(); if (access.IsExternalMemory()) { - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); MemOperand operand = instr->object()->IsConstantOperand() ? MemOperand::StaticVariable( ToExternalReference(LConstantOperand::cast(instr->object()))) @@ -4368,42 +4005,27 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { Register object = ToRegister(instr->object()); __ AssertNotSmi(object); - ASSERT(!representation.IsSmi() || + DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() || IsSmi(LConstantOperand::cast(instr->value()))); if (representation.IsDouble()) { - ASSERT(access.IsInobject()); - ASSERT(!instr->hydrogen()->has_transition()); - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister value = ToDoubleRegister(instr->value()); - __ movsd(FieldOperand(object, offset), value); - } else { - X87Register value = ToX87Register(instr->value()); - X87Mov(FieldOperand(object, offset), value); - } + DCHECK(access.IsInobject()); + DCHECK(!instr->hydrogen()->has_transition()); + DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); + XMMRegister value = ToDoubleRegister(instr->value()); + __ movsd(FieldOperand(object, offset), value); return; } if (instr->hydrogen()->has_transition()) { Handle<Map> transition = instr->hydrogen()->transition_map(); AddDeprecationDependency(transition); - if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { - __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); - } else { + __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); + if (instr->hydrogen()->NeedsWriteBarrierForMap()) { Register temp = ToRegister(instr->temp()); Register temp_map = ToRegister(instr->temp_map()); - __ mov(temp_map, transition); - __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); // Update the write barrier for the map field. - __ RecordWriteField(object, - HeapObject::kMapOffset, - temp_map, - temp, - GetSaveFPRegsMode(isolate()), - OMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); + __ RecordWriteForMap(object, transition, temp_map, temp, kSaveFPRegs); } } @@ -4422,11 +4044,11 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { __ Store(value, operand, representation); } else if (representation.IsInteger32()) { Immediate immediate = ToImmediate(operand_value, representation); - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); __ mov(operand, immediate); } else { Handle<Object> handle_value = ToHandle(operand_value); - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); __ mov(operand, handle_value); } } else { @@ -4442,19 +4064,20 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { offset, value, temp, - GetSaveFPRegsMode(isolate()), + kSaveFPRegs, EMIT_REMEMBERED_SET, - instr->hydrogen()->SmiCheckForWriteBarrier()); + instr->hydrogen()->SmiCheckForWriteBarrier(), + instr->hydrogen()->PointersToHereCheckForValue()); } } void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->object()).is(edx)); - ASSERT(ToRegister(instr->value()).is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->object()).is(StoreIC::ReceiverRegister())); + DCHECK(ToRegister(instr->value()).is(StoreIC::ValueRegister())); - __ mov(ecx, instr->name()); + __ mov(StoreIC::NameRegister(), instr->name()); Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4466,7 +4089,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { __ cmp(ToOperand(instr->length()), ToImmediate(LConstantOperand::cast(instr->index()), instr->hydrogen()->length()->representation())); - cc = ReverseCondition(cc); + cc = CommuteCondition(cc); } else if (instr->length()->IsConstantOperand()) { __ cmp(ToOperand(instr->index()), ToImmediate(LConstantOperand::cast(instr->length()), @@ -4498,27 +4121,15 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { key, instr->hydrogen()->key()->representation(), elements_kind, - 0, - instr->additional_index())); + instr->base_offset())); if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || elements_kind == FLOAT32_ELEMENTS) { - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister xmm_scratch = double_scratch0(); - __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); - __ movss(operand, xmm_scratch); - } else { - __ fld(0); - __ fstp_s(operand); - } + XMMRegister xmm_scratch = double_scratch0(); + __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); + __ movss(operand, xmm_scratch); } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) { - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - __ movsd(operand, ToDoubleRegister(instr->value())); - } else { - X87Mov(operand, ToX87Register(instr->value())); - } + __ movsd(operand, ToDoubleRegister(instr->value())); } else { Register value = ToRegister(instr->value()); switch (elements_kind) { @@ -4569,71 +4180,21 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { instr->key(), instr->hydrogen()->key()->representation(), FAST_DOUBLE_ELEMENTS, - FixedDoubleArray::kHeaderSize - kHeapObjectTag, - instr->additional_index()); + instr->base_offset()); - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister value = ToDoubleRegister(instr->value()); - - if (instr->NeedsCanonicalization()) { - Label have_value; + XMMRegister value = ToDoubleRegister(instr->value()); - __ ucomisd(value, value); - __ j(parity_odd, &have_value, Label::kNear); // NaN. + if (instr->NeedsCanonicalization()) { + Label have_value; - __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); - __ bind(&have_value); - } + __ ucomisd(value, value); + __ j(parity_odd, &have_value, Label::kNear); // NaN. - __ movsd(double_store_operand, value); - } else { - // Can't use SSE2 in the serializer - if (instr->hydrogen()->IsConstantHoleStore()) { - // This means we should store the (double) hole. No floating point - // registers required. - double nan_double = FixedDoubleArray::hole_nan_as_double(); - uint64_t int_val = BitCast<uint64_t, double>(nan_double); - int32_t lower = static_cast<int32_t>(int_val); - int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); - - __ mov(double_store_operand, Immediate(lower)); - Operand double_store_operand2 = BuildFastArrayOperand( - instr->elements(), - instr->key(), - instr->hydrogen()->key()->representation(), - FAST_DOUBLE_ELEMENTS, - FixedDoubleArray::kHeaderSize - kHeapObjectTag + kPointerSize, - instr->additional_index()); - __ mov(double_store_operand2, Immediate(upper)); - } else { - Label no_special_nan_handling; - X87Register value = ToX87Register(instr->value()); - X87Fxch(value); - - if (instr->NeedsCanonicalization()) { - __ fld(0); - __ fld(0); - __ FCmp(); - - __ j(parity_odd, &no_special_nan_handling, Label::kNear); - __ sub(esp, Immediate(kDoubleSize)); - __ fst_d(MemOperand(esp, 0)); - __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), - Immediate(kHoleNanUpper32)); - __ add(esp, Immediate(kDoubleSize)); - Label canonicalize; - __ j(not_equal, &canonicalize, Label::kNear); - __ jmp(&no_special_nan_handling, Label::kNear); - __ bind(&canonicalize); - __ fstp(0); - __ fld_d(Operand::StaticVariable(canonical_nan_reference)); - } - - __ bind(&no_special_nan_handling); - __ fst_d(double_store_operand); - } + __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); + __ bind(&have_value); } + + __ movsd(double_store_operand, value); } @@ -4646,8 +4207,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { instr->key(), instr->hydrogen()->key()->representation(), FAST_ELEMENTS, - FixedArray::kHeaderSize - kHeapObjectTag, - instr->additional_index()); + instr->base_offset()); if (instr->value()->IsRegister()) { __ mov(operand, ToRegister(instr->value())); } else { @@ -4656,27 +4216,28 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { Immediate immediate = ToImmediate(operand_value, Representation::Smi()); __ mov(operand, immediate); } else { - ASSERT(!IsInteger32(operand_value)); + DCHECK(!IsInteger32(operand_value)); Handle<Object> handle_value = ToHandle(operand_value); __ mov(operand, handle_value); } } if (instr->hydrogen()->NeedsWriteBarrier()) { - ASSERT(instr->value()->IsRegister()); + DCHECK(instr->value()->IsRegister()); Register value = ToRegister(instr->value()); - ASSERT(!instr->key()->IsConstantOperand()); + DCHECK(!instr->key()->IsConstantOperand()); SmiCheck check_needed = - instr->hydrogen()->value()->IsHeapObject() + instr->hydrogen()->value()->type().IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; // Compute address of modified element and store it into key register. __ lea(key, operand); __ RecordWrite(elements, key, value, - GetSaveFPRegsMode(isolate()), + kSaveFPRegs, EMIT_REMEMBERED_SET, - check_needed); + check_needed, + instr->hydrogen()->PointersToHereCheckForValue()); } } @@ -4694,10 +4255,10 @@ void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->object()).is(edx)); - ASSERT(ToRegister(instr->key()).is(ecx)); - ASSERT(ToRegister(instr->value()).is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister())); + DCHECK(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister())); + DCHECK(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister())); Handle<Code> ic = instr->strict_mode() == STRICT ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() @@ -4736,13 +4297,13 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), Immediate(to_map)); // Write barrier. - ASSERT_NE(instr->temp(), NULL); + DCHECK_NE(instr->temp(), NULL); __ RecordWriteForMap(object_reg, to_map, new_map_reg, ToRegister(instr->temp()), kDontSaveFPRegs); } else { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(object_reg.is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(object_reg.is(eax)); PushSafepointRegistersScope scope(this); __ mov(ebx, to_map); bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; @@ -4759,9 +4320,8 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { public: DeferredStringCharCodeAt(LCodeGen* codegen, - LStringCharCodeAt* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + LStringCharCodeAt* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredStringCharCodeAt(instr_); } @@ -4771,7 +4331,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { }; DeferredStringCharCodeAt* deferred = - new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_); + new(zone()) DeferredStringCharCodeAt(this, instr); StringCharLoadGenerator::Generate(masm(), factory(), @@ -4806,7 +4366,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { __ SmiTag(index); __ push(index); } - CallRuntimeFromDeferred(Runtime::kHiddenStringCharCodeAt, 2, + CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2, instr, instr->context()); __ AssertSmi(eax); __ SmiUntag(eax); @@ -4818,9 +4378,8 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { public: DeferredStringCharFromCode(LCodeGen* codegen, - LStringCharFromCode* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + LStringCharFromCode* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredStringCharFromCode(instr_); } @@ -4830,12 +4389,12 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { }; DeferredStringCharFromCode* deferred = - new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_); + new(zone()) DeferredStringCharFromCode(this, instr); - ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); + DCHECK(instr->hydrogen()->value()->representation().IsInteger32()); Register char_code = ToRegister(instr->char_code()); Register result = ToRegister(instr->result()); - ASSERT(!char_code.is(result)); + DCHECK(!char_code.is(result)); __ cmp(char_code, String::kMaxOneByteCharCode); __ j(above, deferred->entry()); @@ -4867,9 +4426,9 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { void LCodeGen::DoStringAdd(LStringAdd* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); - ASSERT(ToRegister(instr->left()).is(edx)); - ASSERT(ToRegister(instr->right()).is(eax)); + DCHECK(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->left()).is(edx)); + DCHECK(ToRegister(instr->right()).is(eax)); StringAddStub stub(isolate(), instr->hydrogen()->flags(), instr->hydrogen()->pretenure_flag()); @@ -4880,38 +4439,16 @@ void LCodeGen::DoStringAdd(LStringAdd* instr) { void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { LOperand* input = instr->value(); LOperand* output = instr->result(); - ASSERT(input->IsRegister() || input->IsStackSlot()); - ASSERT(output->IsDoubleRegister()); - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); - } else if (input->IsRegister()) { - Register input_reg = ToRegister(input); - __ push(input_reg); - X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand); - __ pop(input_reg); - } else { - X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand); - } + DCHECK(input->IsRegister() || input->IsStackSlot()); + DCHECK(output->IsDoubleRegister()); + __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); } void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { LOperand* input = instr->value(); LOperand* output = instr->result(); - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - LOperand* temp = instr->temp(); - - __ LoadUint32(ToDoubleRegister(output), - ToRegister(input), - ToDoubleRegister(temp)); - } else { - X87Register res = ToX87Register(output); - X87PrepareToWrite(res); - __ LoadUint32NoSSE2(ToRegister(input)); - X87CommitWrite(res); - } + __ LoadUint32(ToDoubleRegister(output), ToRegister(input)); } @@ -4919,12 +4456,11 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { class DeferredNumberTagI V8_FINAL : public LDeferredCode { public: DeferredNumberTagI(LCodeGen* codegen, - LNumberTagI* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + LNumberTagI* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { - codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), - NULL, SIGNED_INT32); + codegen()->DoDeferredNumberTagIU( + instr_, instr_->value(), instr_->temp(), SIGNED_INT32); } virtual LInstruction* instr() V8_OVERRIDE { return instr_; } private: @@ -4932,11 +4468,11 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { }; LOperand* input = instr->value(); - ASSERT(input->IsRegister() && input->Equals(instr->result())); + DCHECK(input->IsRegister() && input->Equals(instr->result())); Register reg = ToRegister(input); DeferredNumberTagI* deferred = - new(zone()) DeferredNumberTagI(this, instr, x87_stack_); + new(zone()) DeferredNumberTagI(this, instr); __ SmiTag(reg); __ j(overflow, deferred->entry()); __ bind(deferred->exit()); @@ -4946,13 +4482,11 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { void LCodeGen::DoNumberTagU(LNumberTagU* instr) { class DeferredNumberTagU V8_FINAL : public LDeferredCode { public: - DeferredNumberTagU(LCodeGen* codegen, - LNumberTagU* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { - codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), - instr_->temp2(), UNSIGNED_INT32); + codegen()->DoDeferredNumberTagIU( + instr_, instr_->value(), instr_->temp(), UNSIGNED_INT32); } virtual LInstruction* instr() V8_OVERRIDE { return instr_; } private: @@ -4960,11 +4494,11 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { }; LOperand* input = instr->value(); - ASSERT(input->IsRegister() && input->Equals(instr->result())); + DCHECK(input->IsRegister() && input->Equals(instr->result())); Register reg = ToRegister(input); DeferredNumberTagU* deferred = - new(zone()) DeferredNumberTagU(this, instr, x87_stack_); + new(zone()) DeferredNumberTagU(this, instr); __ cmp(reg, Immediate(Smi::kMaxValue)); __ j(above, deferred->entry()); __ SmiTag(reg); @@ -4974,12 +4508,11 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, LOperand* value, - LOperand* temp1, - LOperand* temp2, + LOperand* temp, IntegerSignedness signedness) { Label done, slow; Register reg = ToRegister(value); - Register tmp = ToRegister(temp1); + Register tmp = ToRegister(temp); XMMRegister xmm_scratch = double_scratch0(); if (signedness == SIGNED_INT32) { @@ -4988,27 +4521,9 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, // the value in there. If that fails, call the runtime system. __ SmiUntag(reg); __ xor_(reg, 0x80000000); - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope feature_scope(masm(), SSE2); - __ Cvtsi2sd(xmm_scratch, Operand(reg)); - } else { - __ push(reg); - __ fild_s(Operand(esp, 0)); - __ pop(reg); - } + __ Cvtsi2sd(xmm_scratch, Operand(reg)); } else { - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope feature_scope(masm(), SSE2); - __ LoadUint32(xmm_scratch, reg, ToDoubleRegister(temp2)); - } else { - // There's no fild variant for unsigned values, so zero-extend to a 64-bit - // int manually. - __ push(Immediate(0)); - __ push(reg); - __ fild_d(Operand(esp, 0)); - __ pop(reg); - __ pop(reg); - } + __ LoadUint32(xmm_scratch, reg); } if (FLAG_inline_new) { @@ -5029,11 +4544,11 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, // NumberTagI and NumberTagD use the context from the frame, rather than // the environment's HContext or HInlinedContext value. - // They only call Runtime::kHiddenAllocateHeapNumber. + // They only call Runtime::kAllocateHeapNumber. // The corresponding HChange instructions are added in a phase that does // not have easy access to the local context. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); + __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); __ StoreToSafepointRegisterSlot(reg, eax); @@ -5042,22 +4557,15 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, // Done. Put the value in xmm_scratch into the value of the allocated heap // number. __ bind(&done); - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope feature_scope(masm(), SSE2); - __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); - } else { - __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); - } + __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); } void LCodeGen::DoNumberTagD(LNumberTagD* instr) { class DeferredNumberTagD V8_FINAL : public LDeferredCode { public: - DeferredNumberTagD(LCodeGen* codegen, - LNumberTagD* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredNumberTagD(instr_); } @@ -5068,15 +4576,8 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) { Register reg = ToRegister(instr->result()); - bool use_sse2 = CpuFeatures::IsSupported(SSE2); - if (!use_sse2) { - // Put the value to the top of stack - X87Register src = ToX87Register(instr->value()); - X87LoadForUsage(src); - } - DeferredNumberTagD* deferred = - new(zone()) DeferredNumberTagD(this, instr, x87_stack_); + new(zone()) DeferredNumberTagD(this, instr); if (FLAG_inline_new) { Register tmp = ToRegister(instr->temp()); __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); @@ -5084,13 +4585,8 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) { __ jmp(deferred->entry()); } __ bind(deferred->exit()); - if (use_sse2) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister input_reg = ToDoubleRegister(instr->value()); - __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); - } else { - __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); - } + XMMRegister input_reg = ToDoubleRegister(instr->value()); + __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); } @@ -5104,11 +4600,11 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { PushSafepointRegistersScope scope(this); // NumberTagI and NumberTagD use the context from the frame, rather than // the environment's HContext or HInlinedContext value. - // They only call Runtime::kHiddenAllocateHeapNumber. + // They only call Runtime::kAllocateHeapNumber. // The corresponding HChange instructions are added in a phase that does // not have easy access to the local context. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); + __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); __ StoreToSafepointRegisterSlot(reg, eax); @@ -5134,7 +4630,7 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) { void LCodeGen::DoSmiUntag(LSmiUntag* instr) { LOperand* input = instr->value(); Register result = ToRegister(input); - ASSERT(input->IsRegister() && input->Equals(instr->result())); + DCHECK(input->IsRegister() && input->Equals(instr->result())); if (instr->needs_check()) { __ test(result, Immediate(kSmiTagMask)); DeoptimizeIf(not_zero, instr->environment()); @@ -5145,76 +4641,6 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { } -void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg, - Register temp_reg, - X87Register res_reg, - bool can_convert_undefined_to_nan, - bool deoptimize_on_minus_zero, - LEnvironment* env, - NumberUntagDMode mode) { - Label load_smi, done; - - X87PrepareToWrite(res_reg); - if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { - // Smi check. - __ JumpIfSmi(input_reg, &load_smi, Label::kNear); - - // Heap number map check. - __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), - factory()->heap_number_map()); - if (!can_convert_undefined_to_nan) { - DeoptimizeIf(not_equal, env); - } else { - Label heap_number, convert; - __ j(equal, &heap_number, Label::kNear); - - // Convert undefined (or hole) to NaN. - __ cmp(input_reg, factory()->undefined_value()); - DeoptimizeIf(not_equal, env); - - __ bind(&convert); - ExternalReference nan = - ExternalReference::address_of_canonical_non_hole_nan(); - __ fld_d(Operand::StaticVariable(nan)); - __ jmp(&done, Label::kNear); - - __ bind(&heap_number); - } - // Heap number to x87 conversion. - __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); - if (deoptimize_on_minus_zero) { - __ fldz(); - __ FCmp(); - __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); - __ j(not_zero, &done, Label::kNear); - - // Use general purpose registers to check if we have -0.0 - __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); - __ test(temp_reg, Immediate(HeapNumber::kSignMask)); - __ j(zero, &done, Label::kNear); - - // Pop FPU stack before deoptimizing. - __ fstp(0); - DeoptimizeIf(not_zero, env); - } - __ jmp(&done, Label::kNear); - } else { - ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); - } - - __ bind(&load_smi); - // Clobbering a temp is faster than re-tagging the - // input register since we avoid dependencies. - __ mov(temp_reg, input_reg); - __ SmiUntag(temp_reg); // Untag smi before converting to float. - __ push(temp_reg); - __ fild_s(Operand(esp, 0)); - __ add(esp, Immediate(kPointerSize)); - __ bind(&done); - X87CommitWrite(res_reg); -} - - void LCodeGen::EmitNumberUntagD(Register input_reg, Register temp_reg, XMMRegister result_reg, @@ -5264,7 +4690,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, __ jmp(&done, Label::kNear); } } else { - ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); + DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); } __ bind(&load_smi); @@ -5330,10 +4756,8 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { void LCodeGen::DoTaggedToI(LTaggedToI* instr) { class DeferredTaggedToI V8_FINAL : public LDeferredCode { public: - DeferredTaggedToI(LCodeGen* codegen, - LTaggedToI* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredTaggedToI(instr_, done()); } @@ -5343,15 +4767,15 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { }; LOperand* input = instr->value(); - ASSERT(input->IsRegister()); + DCHECK(input->IsRegister()); Register input_reg = ToRegister(input); - ASSERT(input_reg.is(ToRegister(instr->result()))); + DCHECK(input_reg.is(ToRegister(instr->result()))); if (instr->hydrogen()->value()->representation().IsSmi()) { __ SmiUntag(input_reg); } else { DeferredTaggedToI* deferred = - new(zone()) DeferredTaggedToI(this, instr, x87_stack_); + new(zone()) DeferredTaggedToI(this, instr); // Optimistically untag the input. // If the input is a HeapObject, SmiUntag will set the carry flag. STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); @@ -5366,11 +4790,11 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { LOperand* input = instr->value(); - ASSERT(input->IsRegister()); + DCHECK(input->IsRegister()); LOperand* temp = instr->temp(); - ASSERT(temp->IsRegister()); + DCHECK(temp->IsRegister()); LOperand* result = instr->result(); - ASSERT(result->IsDoubleRegister()); + DCHECK(result->IsDoubleRegister()); Register input_reg = ToRegister(input); bool deoptimize_on_minus_zero = @@ -5381,59 +4805,33 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { NumberUntagDMode mode = value->representation().IsSmi() ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; - if (CpuFeatures::IsSupported(SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister result_reg = ToDoubleRegister(result); - EmitNumberUntagD(input_reg, - temp_reg, - result_reg, - instr->hydrogen()->can_convert_undefined_to_nan(), - deoptimize_on_minus_zero, - instr->environment(), - mode); - } else { - EmitNumberUntagDNoSSE2(input_reg, - temp_reg, - ToX87Register(instr->result()), - instr->hydrogen()->can_convert_undefined_to_nan(), - deoptimize_on_minus_zero, - instr->environment(), - mode); - } + XMMRegister result_reg = ToDoubleRegister(result); + EmitNumberUntagD(input_reg, + temp_reg, + result_reg, + instr->hydrogen()->can_convert_undefined_to_nan(), + deoptimize_on_minus_zero, + instr->environment(), + mode); } void LCodeGen::DoDoubleToI(LDoubleToI* instr) { LOperand* input = instr->value(); - ASSERT(input->IsDoubleRegister()); + DCHECK(input->IsDoubleRegister()); LOperand* result = instr->result(); - ASSERT(result->IsRegister()); + DCHECK(result->IsRegister()); Register result_reg = ToRegister(result); if (instr->truncating()) { - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister input_reg = ToDoubleRegister(input); - __ TruncateDoubleToI(result_reg, input_reg); - } else { - X87Register input_reg = ToX87Register(input); - X87Fxch(input_reg); - __ TruncateX87TOSToI(result_reg); - } + XMMRegister input_reg = ToDoubleRegister(input); + __ TruncateDoubleToI(result_reg, input_reg); } else { Label bailout, done; - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister input_reg = ToDoubleRegister(input); - XMMRegister xmm_scratch = double_scratch0(); - __ DoubleToI(result_reg, input_reg, xmm_scratch, - instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); - } else { - X87Register input_reg = ToX87Register(input); - X87Fxch(input_reg); - __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), - &bailout, Label::kNear); - } + XMMRegister input_reg = ToDoubleRegister(input); + XMMRegister xmm_scratch = double_scratch0(); + __ DoubleToI(result_reg, input_reg, xmm_scratch, + instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); __ jmp(&done, Label::kNear); __ bind(&bailout); DeoptimizeIf(no_condition, instr->environment()); @@ -5444,24 +4842,16 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { LOperand* input = instr->value(); - ASSERT(input->IsDoubleRegister()); + DCHECK(input->IsDoubleRegister()); LOperand* result = instr->result(); - ASSERT(result->IsRegister()); + DCHECK(result->IsRegister()); Register result_reg = ToRegister(result); Label bailout, done; - if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { - CpuFeatureScope scope(masm(), SSE2); - XMMRegister input_reg = ToDoubleRegister(input); - XMMRegister xmm_scratch = double_scratch0(); - __ DoubleToI(result_reg, input_reg, xmm_scratch, - instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); - } else { - X87Register input_reg = ToX87Register(input); - X87Fxch(input_reg); - __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), - &bailout, Label::kNear); - } + XMMRegister input_reg = ToDoubleRegister(input); + XMMRegister xmm_scratch = double_scratch0(); + __ DoubleToI(result_reg, input_reg, xmm_scratch, + instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); __ jmp(&done, Label::kNear); __ bind(&bailout); DeoptimizeIf(no_condition, instr->environment()); @@ -5480,7 +4870,7 @@ void LCodeGen::DoCheckSmi(LCheckSmi* instr) { void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { - if (!instr->hydrogen()->value()->IsHeapObject()) { + if (!instr->hydrogen()->value()->type().IsHeapObject()) { LOperand* input = instr->value(); __ test(ToOperand(input), Immediate(kSmiTagMask)); DeoptimizeIf(zero, instr->environment()); @@ -5520,7 +4910,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); if (IsPowerOf2(mask)) { - ASSERT(tag == 0 || IsPowerOf2(tag)); + DCHECK(tag == 0 || IsPowerOf2(tag)); __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); } else { @@ -5565,11 +4955,8 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { void LCodeGen::DoCheckMaps(LCheckMaps* instr) { class DeferredCheckMaps V8_FINAL : public LDeferredCode { public: - DeferredCheckMaps(LCodeGen* codegen, - LCheckMaps* instr, - Register object, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) { + DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) + : LDeferredCode(codegen), instr_(instr), object_(object) { SetExit(check_maps()); } virtual void Generate() V8_OVERRIDE { @@ -5592,12 +4979,12 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { } LOperand* input = instr->value(); - ASSERT(input->IsRegister()); + DCHECK(input->IsRegister()); Register reg = ToRegister(input); DeferredCheckMaps* deferred = NULL; if (instr->hydrogen()->HasMigrationTarget()) { - deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); + deferred = new(zone()) DeferredCheckMaps(this, instr, reg); __ bind(deferred->check_maps()); } @@ -5622,7 +5009,6 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { - CpuFeatureScope scope(masm(), SSE2); XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); XMMRegister xmm_scratch = double_scratch0(); Register result_reg = ToRegister(instr->result()); @@ -5631,16 +5017,14 @@ void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { - ASSERT(instr->unclamped()->Equals(instr->result())); + DCHECK(instr->unclamped()->Equals(instr->result())); Register value_reg = ToRegister(instr->result()); __ ClampUint8(value_reg); } void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { - CpuFeatureScope scope(masm(), SSE2); - - ASSERT(instr->unclamped()->Equals(instr->result())); + DCHECK(instr->unclamped()->Equals(instr->result())); Register input_reg = ToRegister(instr->unclamped()); XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); XMMRegister xmm_scratch = double_scratch0(); @@ -5674,130 +5058,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { } -void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) { - Register input_reg = ToRegister(instr->unclamped()); - Register result_reg = ToRegister(instr->result()); - Register scratch = ToRegister(instr->scratch()); - Register scratch2 = ToRegister(instr->scratch2()); - Register scratch3 = ToRegister(instr->scratch3()); - Label is_smi, done, heap_number, valid_exponent, - largest_value, zero_result, maybe_nan_or_infinity; - - __ JumpIfSmi(input_reg, &is_smi); - - // Check for heap number - __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), - factory()->heap_number_map()); - __ j(equal, &heap_number, Label::kNear); - - // Check for undefined. Undefined is converted to zero for clamping - // conversions. - __ cmp(input_reg, factory()->undefined_value()); - DeoptimizeIf(not_equal, instr->environment()); - __ jmp(&zero_result, Label::kNear); - - // Heap number - __ bind(&heap_number); - - // Surprisingly, all of the hand-crafted bit-manipulations below are much - // faster than the x86 FPU built-in instruction, especially since "banker's - // rounding" would be additionally very expensive - - // Get exponent word. - __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset)); - __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); - - // Test for negative values --> clamp to zero - __ test(scratch, scratch); - __ j(negative, &zero_result, Label::kNear); - - // Get exponent alone in scratch2. - __ mov(scratch2, scratch); - __ and_(scratch2, HeapNumber::kExponentMask); - __ shr(scratch2, HeapNumber::kExponentShift); - __ j(zero, &zero_result, Label::kNear); - __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1)); - __ j(negative, &zero_result, Label::kNear); - - const uint32_t non_int8_exponent = 7; - __ cmp(scratch2, Immediate(non_int8_exponent + 1)); - // If the exponent is too big, check for special values. - __ j(greater, &maybe_nan_or_infinity, Label::kNear); - - __ bind(&valid_exponent); - // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent - // < 7. The shift bias is the number of bits to shift the mantissa such that - // with an exponent of 7 such the that top-most one is in bit 30, allowing - // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to - // 1). - int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1; - __ lea(result_reg, MemOperand(scratch2, shift_bias)); - // Here result_reg (ecx) is the shift, scratch is the exponent word. Get the - // top bits of the mantissa. - __ and_(scratch, HeapNumber::kMantissaMask); - // Put back the implicit 1 of the mantissa - __ or_(scratch, 1 << HeapNumber::kExponentShift); - // Shift up to round - __ shl_cl(scratch); - // Use "banker's rounding" to spec: If fractional part of number is 0.5, then - // use the bit in the "ones" place and add it to the "halves" place, which has - // the effect of rounding to even. - __ mov(scratch2, scratch); - const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8; - const uint32_t one_bit_shift = one_half_bit_shift + 1; - __ and_(scratch2, Immediate((1 << one_bit_shift) - 1)); - __ cmp(scratch2, Immediate(1 << one_half_bit_shift)); - Label no_round; - __ j(less, &no_round, Label::kNear); - Label round_up; - __ mov(scratch2, Immediate(1 << one_half_bit_shift)); - __ j(greater, &round_up, Label::kNear); - __ test(scratch3, scratch3); - __ j(not_zero, &round_up, Label::kNear); - __ mov(scratch2, scratch); - __ and_(scratch2, Immediate(1 << one_bit_shift)); - __ shr(scratch2, 1); - __ bind(&round_up); - __ add(scratch, scratch2); - __ j(overflow, &largest_value, Label::kNear); - __ bind(&no_round); - __ shr(scratch, 23); - __ mov(result_reg, scratch); - __ jmp(&done, Label::kNear); - - __ bind(&maybe_nan_or_infinity); - // Check for NaN/Infinity, all other values map to 255 - __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1)); - __ j(not_equal, &largest_value, Label::kNear); - - // Check for NaN, which differs from Infinity in that at least one mantissa - // bit is set. - __ and_(scratch, HeapNumber::kMantissaMask); - __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); - __ j(not_zero, &zero_result, Label::kNear); // M!=0 --> NaN - // Infinity -> Fall through to map to 255. - - __ bind(&largest_value); - __ mov(result_reg, Immediate(255)); - __ jmp(&done, Label::kNear); - - __ bind(&zero_result); - __ xor_(result_reg, result_reg); - __ jmp(&done, Label::kNear); - - // smi - __ bind(&is_smi); - if (!input_reg.is(result_reg)) { - __ mov(result_reg, input_reg); - } - __ SmiUntag(result_reg); - __ ClampUint8(result_reg); - __ bind(&done); -} - - void LCodeGen::DoDoubleBits(LDoubleBits* instr) { - CpuFeatureScope scope(masm(), SSE2); XMMRegister value_reg = ToDoubleRegister(instr->value()); Register result_reg = ToRegister(instr->result()); if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { @@ -5819,7 +5080,6 @@ void LCodeGen::DoConstructDouble(LConstructDouble* instr) { Register hi_reg = ToRegister(instr->hi()); Register lo_reg = ToRegister(instr->lo()); XMMRegister result_reg = ToDoubleRegister(instr->result()); - CpuFeatureScope scope(masm(), SSE2); if (CpuFeatures::IsSupported(SSE4_1)) { CpuFeatureScope scope2(masm(), SSE4_1); @@ -5838,10 +5098,8 @@ void LCodeGen::DoConstructDouble(LConstructDouble* instr) { void LCodeGen::DoAllocate(LAllocate* instr) { class DeferredAllocate V8_FINAL : public LDeferredCode { public: - DeferredAllocate(LCodeGen* codegen, - LAllocate* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + DeferredAllocate(LCodeGen* codegen, LAllocate* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredAllocate(instr_); } @@ -5850,8 +5108,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) { LAllocate* instr_; }; - DeferredAllocate* deferred = - new(zone()) DeferredAllocate(this, instr, x87_stack_); + DeferredAllocate* deferred = new(zone()) DeferredAllocate(this, instr); Register result = ToRegister(instr->result()); Register temp = ToRegister(instr->temp()); @@ -5862,11 +5119,11 @@ void LCodeGen::DoAllocate(LAllocate* instr) { flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); } if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { - ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); - ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { - ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); } @@ -5914,7 +5171,7 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { PushSafepointRegistersScope scope(this); if (instr->size()->IsRegister()) { Register size = ToRegister(instr->size()); - ASSERT(!size.is(result)); + DCHECK(!size.is(result)); __ SmiTag(ToRegister(instr->size())); __ push(size); } else { @@ -5931,11 +5188,11 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { int flags = AllocateDoubleAlignFlag::encode( instr->hydrogen()->MustAllocateDoubleAligned()); if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { - ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); - ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { - ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); } else { flags = AllocateTargetSpace::update(flags, NEW_SPACE); @@ -5943,20 +5200,20 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { __ push(Immediate(Smi::FromInt(flags))); CallRuntimeFromDeferred( - Runtime::kHiddenAllocateInTargetSpace, 2, instr, instr->context()); + Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); __ StoreToSafepointRegisterSlot(result, eax); } void LCodeGen::DoToFastProperties(LToFastProperties* instr) { - ASSERT(ToRegister(instr->value()).is(eax)); + DCHECK(ToRegister(instr->value()).is(eax)); __ push(eax); CallRuntime(Runtime::kToFastProperties, 1, instr); } void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->context()).is(esi)); Label materialized; // Registers will be used as follows: // ecx = literals array. @@ -5976,7 +5233,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); __ push(Immediate(instr->hydrogen()->pattern())); __ push(Immediate(instr->hydrogen()->flags())); - CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4, instr); + CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); __ mov(ebx, eax); __ bind(&materialized); @@ -5988,7 +5245,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { __ bind(&runtime_allocate); __ push(ebx); __ push(Immediate(Smi::FromInt(size))); - CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1, instr); + CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); __ pop(ebx); __ bind(&allocated); @@ -6008,7 +5265,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->context()).is(esi)); // Use the fast case closure allocation code that allocates in new // space for nested functions that don't need literals cloning. bool pretenure = instr->hydrogen()->pretenure(); @@ -6023,13 +5280,13 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { __ push(Immediate(instr->hydrogen()->shared_info())); __ push(Immediate(pretenure ? factory()->true_value() : factory()->false_value())); - CallRuntime(Runtime::kHiddenNewClosure, 3, instr); + CallRuntime(Runtime::kNewClosure, 3, instr); } } void LCodeGen::DoTypeof(LTypeof* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->context()).is(esi)); LOperand* input = instr->value(); EmitPushTaggedOperand(input); CallRuntime(Runtime::kTypeof, 1, instr); @@ -6083,11 +5340,6 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) { __ cmp(input, factory()->false_value()); final_branch_condition = equal; - } else if (FLAG_harmony_typeof && - String::Equals(type_name, factory()->null_string())) { - __ cmp(input, factory()->null_value()); - final_branch_condition = equal; - } else if (String::Equals(type_name, factory()->undefined_string())) { __ cmp(input, factory()->undefined_value()); __ j(equal, true_label, true_distance); @@ -6108,10 +5360,8 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) { } else if (String::Equals(type_name, factory()->object_string())) { __ JumpIfSmi(input, false_label, false_distance); - if (!FLAG_harmony_typeof) { - __ cmp(input, factory()->null_value()); - __ j(equal, true_label, true_distance); - } + __ cmp(input, factory()->null_value()); + __ j(equal, true_label, true_distance); __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); __ j(below, false_label, false_distance); __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); @@ -6170,7 +5420,7 @@ void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { void LCodeGen::DoLazyBailout(LLazyBailout* instr) { last_lazy_deopt_pc_ = masm()->pc_offset(); - ASSERT(instr->HasEnvironment()); + DCHECK(instr->HasEnvironment()); LEnvironment* env = instr->environment(); RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); @@ -6204,10 +5454,10 @@ void LCodeGen::DoDummyUse(LDummyUse* instr) { void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { PushSafepointRegistersScope scope(this); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kHiddenStackGuard); + __ CallRuntimeSaveDoubles(Runtime::kStackGuard); RecordSafepointWithLazyDeopt( instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); - ASSERT(instr->HasEnvironment()); + DCHECK(instr->HasEnvironment()); LEnvironment* env = instr->environment(); safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); } @@ -6216,10 +5466,8 @@ void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { void LCodeGen::DoStackCheck(LStackCheck* instr) { class DeferredStackCheck V8_FINAL : public LDeferredCode { public: - DeferredStackCheck(LCodeGen* codegen, - LStackCheck* instr, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), instr_(instr) { } + DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) + : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredStackCheck(instr_); } @@ -6228,7 +5476,7 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { LStackCheck* instr_; }; - ASSERT(instr->HasEnvironment()); + DCHECK(instr->HasEnvironment()); LEnvironment* env = instr->environment(); // There is no LLazyBailout instruction for stack-checks. We have to // prepare for lazy deoptimization explicitly here. @@ -6240,17 +5488,17 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { __ cmp(esp, Operand::StaticVariable(stack_limit)); __ j(above_equal, &done, Label::kNear); - ASSERT(instr->context()->IsRegister()); - ASSERT(ToRegister(instr->context()).is(esi)); + DCHECK(instr->context()->IsRegister()); + DCHECK(ToRegister(instr->context()).is(esi)); CallCode(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET, instr); __ bind(&done); } else { - ASSERT(instr->hydrogen()->is_backwards_branch()); + DCHECK(instr->hydrogen()->is_backwards_branch()); // Perform stack overflow check if this goto needs it before jumping. DeferredStackCheck* deferred_stack_check = - new(zone()) DeferredStackCheck(this, instr, x87_stack_); + new(zone()) DeferredStackCheck(this, instr); ExternalReference stack_limit = ExternalReference::address_of_stack_limit(isolate()); __ cmp(esp, Operand::StaticVariable(stack_limit)); @@ -6274,7 +5522,7 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) { // If the environment were already registered, we would have no way of // backpatching it with the spill slot operands. - ASSERT(!environment->HasBeenRegistered()); + DCHECK(!environment->HasBeenRegistered()); RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); GenerateOsrPrologue(); @@ -6282,7 +5530,7 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) { void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { - ASSERT(ToRegister(instr->context()).is(esi)); + DCHECK(ToRegister(instr->context()).is(esi)); __ cmp(eax, isolate()->factory()->undefined_value()); DeoptimizeIf(equal, instr->environment()); @@ -6364,9 +5612,8 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { DeferredLoadMutableDouble(LCodeGen* codegen, LLoadFieldByIndex* instr, Register object, - Register index, - const X87Stack& x87_stack) - : LDeferredCode(codegen, x87_stack), + Register index) + : LDeferredCode(codegen), instr_(instr), object_(object), index_(index) { @@ -6386,7 +5633,7 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { DeferredLoadMutableDouble* deferred; deferred = new(zone()) DeferredLoadMutableDouble( - this, instr, object, index, x87_stack_); + this, instr, object, index); Label out_of_object, done; __ test(index, Immediate(Smi::FromInt(1))); @@ -6415,6 +5662,21 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { } +void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { + Register context = ToRegister(instr->context()); + __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), context); +} + + +void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) { + Handle<ScopeInfo> scope_info = instr->scope_info(); + __ Push(scope_info); + __ push(ToRegister(instr->function())); + CallRuntime(Runtime::kPushBlockContext, 2, instr); + RecordSafepoint(Safepoint::kNoLazyDeopt); +} + + #undef __ } } // namespace v8::internal |