| Index: src/ia32/lithium-codegen-ia32.cc
|
| diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
|
| index 8c1175d865e608dcc7bbabcebfd9b31a2f3eed33..10115b1ac4744b14b0043293e0fc783b862502f5 100644
|
| --- a/src/ia32/lithium-codegen-ia32.cc
|
| +++ b/src/ia32/lithium-codegen-ia32.cc
|
| @@ -48,7 +48,7 @@ static SaveFPRegsMode GetSaveFPRegsMode() {
|
|
|
| // When invoking builtins, we need to record the safepoint in the middle of
|
| // the invoke instruction sequence generated by the macro assembler.
|
| -class SafepointGenerator : public CallWrapper {
|
| +class SafepointGenerator V8_FINAL : public CallWrapper {
|
| public:
|
| SafepointGenerator(LCodeGen* codegen,
|
| LPointerMap* pointers,
|
| @@ -56,11 +56,11 @@ class SafepointGenerator : public CallWrapper {
|
| : codegen_(codegen),
|
| pointers_(pointers),
|
| deopt_mode_(mode) {}
|
| - virtual ~SafepointGenerator() { }
|
| + virtual ~SafepointGenerator() {}
|
|
|
| - virtual void BeforeCall(int call_size) const {}
|
| + virtual void BeforeCall(int call_size) const V8_OVERRIDE {}
|
|
|
| - virtual void AfterCall() const {
|
| + virtual void AfterCall() const V8_OVERRIDE {
|
| codegen_->RecordSafepoint(pointers_, deopt_mode_);
|
| }
|
|
|
| @@ -359,10 +359,9 @@ bool LCodeGen::GenerateBody() {
|
|
|
| instr->CompileToNative(this);
|
|
|
| - if (!CpuFeatures::IsSupported(SSE2)) {
|
| - if (FLAG_debug_code && FLAG_enable_slow_asserts) {
|
| - __ VerifyX87StackDepth(x87_stack_depth_);
|
| - }
|
| + if (!CpuFeatures::IsSupported(SSE2) &&
|
| + FLAG_debug_code && FLAG_enable_slow_asserts) {
|
| + __ VerifyX87StackDepth(x87_stack_.depth());
|
| }
|
| }
|
| EnsureSpaceForLazyDeopt();
|
| @@ -497,21 +496,21 @@ XMMRegister LCodeGen::ToDoubleRegister(int index) const {
|
|
|
|
|
| void LCodeGen::X87LoadForUsage(X87Register reg) {
|
| - ASSERT(X87StackContains(reg));
|
| - X87Fxch(reg);
|
| - x87_stack_depth_--;
|
| + ASSERT(x87_stack_.Contains(reg));
|
| + x87_stack_.Fxch(reg);
|
| + x87_stack_.pop();
|
| }
|
|
|
|
|
| -void LCodeGen::X87Fxch(X87Register reg, int other_slot) {
|
| - ASSERT(X87StackContains(reg) && x87_stack_depth_ > other_slot);
|
| - int i = X87ArrayIndex(reg);
|
| - int st = x87_st2idx(i);
|
| +void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
|
| + ASSERT(Contains(reg) && stack_depth_ > other_slot);
|
| + int i = ArrayIndex(reg);
|
| + int st = st2idx(i);
|
| if (st != other_slot) {
|
| - int other_i = x87_st2idx(other_slot);
|
| - X87Register other = x87_stack_[other_i];
|
| - x87_stack_[other_i] = reg;
|
| - x87_stack_[i] = other;
|
| + 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) {
|
| @@ -525,88 +524,101 @@ void LCodeGen::X87Fxch(X87Register reg, int other_slot) {
|
| }
|
|
|
|
|
| -int LCodeGen::x87_st2idx(int pos) {
|
| - return x87_stack_depth_ - pos - 1;
|
| +int LCodeGen::X87Stack::st2idx(int pos) {
|
| + return stack_depth_ - pos - 1;
|
| }
|
|
|
|
|
| -int LCodeGen::X87ArrayIndex(X87Register reg) {
|
| - for (int i = 0; i < x87_stack_depth_; i++) {
|
| - if (x87_stack_[i].is(reg)) return i;
|
| +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::X87StackContains(X87Register reg) {
|
| - for (int i = 0; i < x87_stack_depth_; i++) {
|
| - if (x87_stack_[i].is(reg)) return true;
|
| +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::X87Free(X87Register reg) {
|
| - ASSERT(X87StackContains(reg));
|
| - int i = X87ArrayIndex(reg);
|
| - int st = x87_st2idx(i);
|
| +void LCodeGen::X87Stack::Free(X87Register reg) {
|
| + 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 = x87_st2idx(0);
|
| - x87_stack_[i] = x87_stack_[tos_i];
|
| + int tos_i = st2idx(0);
|
| + stack_[i] = stack_[tos_i];
|
| }
|
| - x87_stack_depth_--;
|
| + pop();
|
| __ fstp(st);
|
| }
|
|
|
|
|
| void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
|
| - if (X87StackContains(dst)) {
|
| - X87Fxch(dst);
|
| + if (x87_stack_.Contains(dst)) {
|
| + x87_stack_.Fxch(dst);
|
| __ fstp(0);
|
| } else {
|
| - ASSERT(x87_stack_depth_ < X87Register::kNumAllocatableRegisters);
|
| - x87_stack_[x87_stack_depth_] = dst;
|
| - x87_stack_depth_++;
|
| + x87_stack_.push(dst);
|
| }
|
| X87Fld(src, opts);
|
| }
|
|
|
|
|
| void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
|
| - if (opts == kX87DoubleOperand) {
|
| - __ fld_d(src);
|
| - } else if (opts == kX87FloatOperand) {
|
| - __ fld_s(src);
|
| - } else if (opts == kX87IntOperand) {
|
| - __ fild_s(src);
|
| - } else {
|
| - UNREACHABLE();
|
| + 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) {
|
| - X87Fxch(src);
|
| - __ fst_d(dst);
|
| +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::X87PrepareToWrite(X87Register reg) {
|
| - if (X87StackContains(reg)) {
|
| - X87Free(reg);
|
| +void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
|
| + if (Contains(reg)) {
|
| + Free(reg);
|
| }
|
| // Mark this register as the next register to write to
|
| - x87_stack_[x87_stack_depth_] = reg;
|
| + stack_[stack_depth_] = reg;
|
| }
|
|
|
|
|
| -void LCodeGen::X87CommitWrite(X87Register reg) {
|
| +void LCodeGen::X87Stack::CommitWrite(X87Register reg) {
|
| // Assert the reg is prepared to write, but not on the virtual stack yet
|
| - ASSERT(!X87StackContains(reg) && x87_stack_[x87_stack_depth_].is(reg) &&
|
| - x87_stack_depth_ < X87Register::kNumAllocatableRegisters);
|
| - x87_stack_depth_++;
|
| + ASSERT(!Contains(reg) && stack_[stack_depth_].is(reg) &&
|
| + stack_depth_ < X87Register::kNumAllocatableRegisters);
|
| + stack_depth_++;
|
| }
|
|
|
|
|
| @@ -614,38 +626,47 @@ void LCodeGen::X87PrepareBinaryOp(
|
| X87Register left, X87Register right, X87Register result) {
|
| // You need to use DefineSameAsFirst for x87 instructions
|
| ASSERT(result.is(left));
|
| - X87Fxch(right, 1);
|
| - X87Fxch(left);
|
| + x87_stack_.Fxch(right, 1);
|
| + x87_stack_.Fxch(left);
|
| }
|
|
|
|
|
| -void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) {
|
| - if (x87_stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) {
|
| +void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
|
| + if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) {
|
| bool double_inputs = instr->HasDoubleRegisterInput();
|
|
|
| // Flush stack from tos down, since FreeX87() will mess with tos
|
| - for (int i = x87_stack_depth_-1; i >= 0; i--) {
|
| - X87Register reg = x87_stack_[i];
|
| + 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, this)) {
|
| + if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
|
| continue;
|
| }
|
| - X87Free(reg);
|
| - if (i < x87_stack_depth_-1) i++;
|
| + Free(reg);
|
| + if (i < stack_depth_-1) i++;
|
| }
|
| }
|
| if (instr->IsReturn()) {
|
| - while (x87_stack_depth_ > 0) {
|
| + while (stack_depth_ > 0) {
|
| __ fstp(0);
|
| - x87_stack_depth_--;
|
| + stack_depth_--;
|
| }
|
| }
|
| }
|
|
|
|
|
| void LCodeGen::EmitFlushX87ForDeopt() {
|
| - for (int i = 0; i < x87_stack_depth_; i++) __ fstp(0);
|
| + // 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);
|
| }
|
|
|
|
|
| @@ -1003,7 +1024,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
|
| // 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) {
|
| + if (x87_stack_.depth() > 0) {
|
| Label done;
|
| if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
|
| EmitFlushX87ForDeopt();
|
| @@ -1441,6 +1462,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
| __ cmp(dividend, 0);
|
| __ j(less, &negative, Label::kNear);
|
| __ sar(dividend, power);
|
| + if (divisor < 0) __ neg(dividend);
|
| __ jmp(&done, Label::kNear);
|
|
|
| __ bind(&negative);
|
| @@ -1865,15 +1887,16 @@ 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(SSE2)) {
|
| __ push(Immediate(upper));
|
| __ push(Immediate(lower));
|
| - X87Mov(ToX87Register(instr->result()), Operand(esp, 0));
|
| + X87Register reg = ToX87Register(instr->result());
|
| + X87Mov(reg, Operand(esp, 0));
|
| __ add(Operand(esp), Immediate(kDoubleSize));
|
| } else {
|
| CpuFeatureScope scope1(masm(), SSE2);
|
| - ASSERT(instr->result()->IsDoubleRegister());
|
| XMMRegister res = ToDoubleRegister(instr->result());
|
| if (int_val == 0) {
|
| __ xorps(res, res);
|
| @@ -2233,6 +2256,17 @@ void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
|
| }
|
|
|
|
|
| +template<class InstrType>
|
| +void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
|
| + int false_block = instr->FalseDestination(chunk_);
|
| + if (cc == no_condition) {
|
| + __ jmp(chunk_->GetAssemblyLabel(false_block));
|
| + } else {
|
| + __ j(cc, chunk_->GetAssemblyLabel(false_block));
|
| + }
|
| +}
|
| +
|
| +
|
| void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
|
| Representation r = instr->hydrogen()->value()->representation();
|
| if (r.IsSmiOrInteger32() || r.IsDouble()) {
|
| @@ -2255,7 +2289,6 @@ void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
|
| void LCodeGen::DoBranch(LBranch* instr) {
|
| Representation r = instr->hydrogen()->value()->representation();
|
| if (r.IsSmiOrInteger32()) {
|
| - ASSERT(!info()->IsStub());
|
| Register reg = ToRegister(instr->value());
|
| __ test(reg, Operand(reg));
|
| EmitBranch(instr, not_zero);
|
| @@ -2483,6 +2516,51 @@ void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
|
| }
|
|
|
|
|
| +void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
|
| + if (instr->hydrogen()->representation().IsTagged()) {
|
| + Register input_reg = ToRegister(instr->object());
|
| + __ cmp(input_reg, factory()->the_hole_value());
|
| + EmitBranch(instr, equal);
|
| + 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);
|
| + __ fstp(0);
|
| + EmitFalseBranch(instr, no_condition);
|
| + __ bind(&ok);
|
| + }
|
| +
|
| +
|
| + __ sub(esp, Immediate(kDoubleSize));
|
| + if (use_sse2) {
|
| + CpuFeatureScope scope(masm(), SSE2);
|
| + XMMRegister input_reg = ToDoubleRegister(instr->object());
|
| + __ movdbl(MemOperand(esp, 0), input_reg);
|
| + } else {
|
| + __ fstp_d(MemOperand(esp, 0));
|
| + }
|
| +
|
| + __ add(esp, Immediate(kDoubleSize));
|
| + int offset = sizeof(kHoleNanUpper32);
|
| + __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
|
| + EmitBranch(instr, equal);
|
| +}
|
| +
|
| +
|
| Condition LCodeGen::EmitIsObject(Register input,
|
| Register temp1,
|
| Label* is_not_object,
|
| @@ -2760,15 +2838,15 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
|
|
|
|
|
| void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
|
| - class DeferredInstanceOfKnownGlobal: public LDeferredCode {
|
| + class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
|
| LInstanceOfKnownGlobal* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() {
|
| + virtual void Generate() V8_OVERRIDE {
|
| codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
|
| }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| Label* map_check() { return &map_check_; }
|
| private:
|
| LInstanceOfKnownGlobal* instr_;
|
| @@ -3122,47 +3200,6 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
|
| }
|
|
|
|
|
| -void LCodeGen::EmitLoadFieldOrConstant(Register result,
|
| - Register object,
|
| - Handle<Map> type,
|
| - Handle<String> name,
|
| - LEnvironment* env) {
|
| - LookupResult lookup(isolate());
|
| - type->LookupDescriptor(NULL, *name, &lookup);
|
| - ASSERT(lookup.IsFound() || lookup.IsCacheable());
|
| - if (lookup.IsField()) {
|
| - int index = lookup.GetLocalFieldIndexFromMap(*type);
|
| - int offset = index * kPointerSize;
|
| - if (index < 0) {
|
| - // Negative property indices are in-object properties, indexed
|
| - // from the end of the fixed part of the object.
|
| - __ mov(result, FieldOperand(object, offset + type->instance_size()));
|
| - } else {
|
| - // Non-negative property indices are in the properties array.
|
| - __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
|
| - __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize));
|
| - }
|
| - } else if (lookup.IsConstant()) {
|
| - Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
|
| - __ LoadObject(result, constant);
|
| - } else {
|
| - // Negative lookup.
|
| - // Check prototypes.
|
| - Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
|
| - Heap* heap = type->GetHeap();
|
| - while (*current != heap->null_value()) {
|
| - __ LoadHeapObject(result, current);
|
| - __ cmp(FieldOperand(result, HeapObject::kMapOffset),
|
| - Handle<Map>(current->map()));
|
| - DeoptimizeIf(not_equal, env);
|
| - current =
|
| - Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
|
| - }
|
| - __ mov(result, factory()->undefined_value());
|
| - }
|
| -}
|
| -
|
| -
|
| void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
|
| ASSERT(!operand->IsDoubleRegister());
|
| if (operand->IsConstantOperand()) {
|
| @@ -3181,68 +3218,6 @@ void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
|
| }
|
|
|
|
|
| -// Check for cases where EmitLoadFieldOrConstantFunction needs to walk the
|
| -// prototype chain, which causes unbounded code generation.
|
| -static bool CompactEmit(SmallMapList* list,
|
| - Handle<String> name,
|
| - int i,
|
| - Isolate* isolate) {
|
| - Handle<Map> map = list->at(i);
|
| - LookupResult lookup(isolate);
|
| - map->LookupDescriptor(NULL, *name, &lookup);
|
| - return lookup.IsField() || lookup.IsConstant();
|
| -}
|
| -
|
| -
|
| -void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
|
| - Register object = ToRegister(instr->object());
|
| - Register result = ToRegister(instr->result());
|
| -
|
| - int map_count = instr->hydrogen()->types()->length();
|
| - bool need_generic = instr->hydrogen()->need_generic();
|
| -
|
| - if (map_count == 0 && !need_generic) {
|
| - DeoptimizeIf(no_condition, instr->environment());
|
| - return;
|
| - }
|
| - Handle<String> name = instr->hydrogen()->name();
|
| - Label done;
|
| - bool all_are_compact = true;
|
| - for (int i = 0; i < map_count; ++i) {
|
| - if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) {
|
| - all_are_compact = false;
|
| - break;
|
| - }
|
| - }
|
| - for (int i = 0; i < map_count; ++i) {
|
| - bool last = (i == map_count - 1);
|
| - Handle<Map> map = instr->hydrogen()->types()->at(i);
|
| - Label check_passed;
|
| - __ CompareMap(object, map, &check_passed);
|
| - if (last && !need_generic) {
|
| - DeoptimizeIf(not_equal, instr->environment());
|
| - __ bind(&check_passed);
|
| - EmitLoadFieldOrConstant(result, object, map, name, instr->environment());
|
| - } else {
|
| - Label next;
|
| - bool compact = all_are_compact ? true :
|
| - CompactEmit(instr->hydrogen()->types(), name, i, isolate());
|
| - __ j(not_equal, &next, compact ? Label::kNear : Label::kFar);
|
| - __ bind(&check_passed);
|
| - EmitLoadFieldOrConstant(result, object, map, name, instr->environment());
|
| - __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar);
|
| - __ bind(&next);
|
| - }
|
| - }
|
| - if (need_generic) {
|
| - __ mov(ecx, name);
|
| - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
|
| - CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
| - }
|
| - __ bind(&done);
|
| -}
|
| -
|
| -
|
| void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
| ASSERT(ToRegister(instr->context()).is(esi));
|
| ASSERT(ToRegister(instr->object()).is(edx));
|
| @@ -3831,14 +3806,14 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
|
|
|
| void LCodeGen::DoMathAbs(LMathAbs* instr) {
|
| // Class for deferred case.
|
| - class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
|
| + class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() {
|
| + virtual void Generate() V8_OVERRIDE {
|
| codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
|
| }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LMathAbs* instr_;
|
| };
|
| @@ -4071,12 +4046,12 @@ void LCodeGen::DoPower(LPower* instr) {
|
|
|
|
|
| void LCodeGen::DoRandom(LRandom* instr) {
|
| - class DeferredDoRandom: public LDeferredCode {
|
| + class DeferredDoRandom V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() { codegen()->DoDeferredRandom(instr_); }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredRandom(instr_); }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LRandom* instr_;
|
| };
|
| @@ -4195,6 +4170,9 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
|
|
| void LCodeGen::DoMathTan(LMathTan* instr) {
|
| ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
|
| + // Set the context register to a GC-safe fake value. Clobbering it is
|
| + // OK because this instruction is marked as a call.
|
| + __ Set(esi, Immediate(0));
|
| TranscendentalCacheStub stub(TranscendentalCache::TAN,
|
| TranscendentalCacheStub::UNTAGGED);
|
| CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| @@ -4203,6 +4181,9 @@ void LCodeGen::DoMathTan(LMathTan* instr) {
|
|
|
| void LCodeGen::DoMathCos(LMathCos* instr) {
|
| ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
|
| + // Set the context register to a GC-safe fake value. Clobbering it is
|
| + // OK because this instruction is marked as a call.
|
| + __ Set(esi, Immediate(0));
|
| TranscendentalCacheStub stub(TranscendentalCache::COS,
|
| TranscendentalCacheStub::UNTAGGED);
|
| CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| @@ -4211,6 +4192,9 @@ void LCodeGen::DoMathCos(LMathCos* instr) {
|
|
|
| void LCodeGen::DoMathSin(LMathSin* instr) {
|
| ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
|
| + // Set the context register to a GC-safe fake value. Clobbering it is
|
| + // OK because this instruction is marked as a call.
|
| + __ Set(esi, Immediate(0));
|
| TranscendentalCacheStub stub(TranscendentalCache::SIN,
|
| TranscendentalCacheStub::UNTAGGED);
|
| CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| @@ -4797,12 +4781,14 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
|
|
|
|
|
| void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
| - class DeferredStringCharCodeAt: public LDeferredCode {
|
| + class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual void Generate() V8_OVERRIDE {
|
| + codegen()->DoDeferredStringCharCodeAt(instr_);
|
| + }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LStringCharCodeAt* instr_;
|
| };
|
| @@ -4852,12 +4838,14 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
|
|
|
|
|
| void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
|
| - class DeferredStringCharFromCode: public LDeferredCode {
|
| + class DeferredStringCharFromCode V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual void Generate() V8_OVERRIDE {
|
| + codegen()->DoDeferredStringCharFromCode(instr_);
|
| + }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LStringCharFromCode* instr_;
|
| };
|
| @@ -4908,15 +4896,20 @@ 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);
|
| - LOperand* input = instr->value();
|
| - ASSERT(input->IsRegister() || input->IsStackSlot());
|
| - LOperand* output = instr->result();
|
| - ASSERT(output->IsDoubleRegister());
|
| __ 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 {
|
| - UNREACHABLE();
|
| + X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
|
| }
|
| }
|
|
|
| @@ -4944,14 +4937,14 @@ void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
|
|
|
|
|
| void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
|
| - class DeferredNumberTagI: public LDeferredCode {
|
| + class DeferredNumberTagI V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() {
|
| + virtual void Generate() V8_OVERRIDE {
|
| codegen()->DoDeferredNumberTagI(instr_, instr_->value(), SIGNED_INT32);
|
| }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LNumberTagI* instr_;
|
| };
|
| @@ -4968,14 +4961,14 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
|
|
|
|
|
| void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
|
| - class DeferredNumberTagU: public LDeferredCode {
|
| + class DeferredNumberTagU V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() {
|
| + virtual void Generate() V8_OVERRIDE {
|
| codegen()->DoDeferredNumberTagI(instr_, instr_->value(), UNSIGNED_INT32);
|
| }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LNumberTagU* instr_;
|
| };
|
| @@ -5071,25 +5064,20 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr,
|
|
|
|
|
| void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
|
| - class DeferredNumberTagD: public LDeferredCode {
|
| + class DeferredNumberTagD V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual void Generate() V8_OVERRIDE {
|
| + codegen()->DoDeferredNumberTagD(instr_);
|
| + }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LNumberTagD* instr_;
|
| };
|
|
|
| Register reg = ToRegister(instr->result());
|
|
|
| - bool convert_hole = false;
|
| - HValue* change_input = instr->hydrogen()->value();
|
| - if (change_input->IsLoadKeyed()) {
|
| - HLoadKeyed* load = HLoadKeyed::cast(change_input);
|
| - convert_hole = load->UsesMustHandleHole();
|
| - }
|
| -
|
| bool use_sse2 = CpuFeatures::IsSupported(SSE2);
|
| if (!use_sse2) {
|
| // Put the value to the top of stack
|
| @@ -5097,54 +5085,6 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
|
| X87LoadForUsage(src);
|
| }
|
|
|
| - Label no_special_nan_handling;
|
| - Label done;
|
| - if (convert_hole) {
|
| - if (use_sse2) {
|
| - CpuFeatureScope scope(masm(), SSE2);
|
| - XMMRegister input_reg = ToDoubleRegister(instr->value());
|
| - __ ucomisd(input_reg, input_reg);
|
| - } else {
|
| - __ fld(0);
|
| - __ fld(0);
|
| - __ FCmp();
|
| - }
|
| -
|
| - __ j(parity_odd, &no_special_nan_handling);
|
| - __ sub(esp, Immediate(kDoubleSize));
|
| - if (use_sse2) {
|
| - CpuFeatureScope scope(masm(), SSE2);
|
| - XMMRegister input_reg = ToDoubleRegister(instr->value());
|
| - __ movdbl(MemOperand(esp, 0), input_reg);
|
| - } else {
|
| - __ fld(0);
|
| - __ fstp_d(MemOperand(esp, 0));
|
| - }
|
| - __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
|
| - Immediate(kHoleNanUpper32));
|
| - Label canonicalize;
|
| - __ j(not_equal, &canonicalize);
|
| - __ add(esp, Immediate(kDoubleSize));
|
| - __ mov(reg, factory()->the_hole_value());
|
| - if (!use_sse2) {
|
| - __ fstp(0);
|
| - }
|
| - __ jmp(&done);
|
| - __ bind(&canonicalize);
|
| - __ add(esp, Immediate(kDoubleSize));
|
| - ExternalReference nan =
|
| - ExternalReference::address_of_canonical_non_hole_nan();
|
| - if (use_sse2) {
|
| - CpuFeatureScope scope(masm(), SSE2);
|
| - XMMRegister input_reg = ToDoubleRegister(instr->value());
|
| - __ movdbl(input_reg, Operand::StaticVariable(nan));
|
| - } else {
|
| - __ fstp(0);
|
| - __ fld_d(Operand::StaticVariable(nan));
|
| - }
|
| - }
|
| -
|
| - __ bind(&no_special_nan_handling);
|
| DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
|
| if (FLAG_inline_new) {
|
| Register tmp = ToRegister(instr->temp());
|
| @@ -5160,7 +5100,6 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
|
| } else {
|
| __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
|
| }
|
| - __ bind(&done);
|
| }
|
|
|
|
|
| @@ -5210,23 +5149,21 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
| void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
|
| Register temp_reg,
|
| X87Register res_reg,
|
| - bool allow_undefined_as_nan,
|
| + bool can_convert_undefined_to_nan,
|
| bool deoptimize_on_minus_zero,
|
| LEnvironment* env,
|
| NumberUntagDMode mode) {
|
| Label load_smi, done;
|
|
|
| X87PrepareToWrite(res_reg);
|
| - STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
|
| - NUMBER_CANDIDATE_IS_ANY_TAGGED);
|
| - if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
|
| + 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 (!allow_undefined_as_nan) {
|
| + if (!can_convert_undefined_to_nan) {
|
| DeoptimizeIf(not_equal, env);
|
| } else {
|
| Label heap_number, convert;
|
| @@ -5234,10 +5171,6 @@ void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
|
|
|
| // Convert undefined (or hole) to NaN.
|
| __ cmp(input_reg, factory()->undefined_value());
|
| - if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
|
| - __ j(equal, &convert, Label::kNear);
|
| - __ cmp(input_reg, factory()->the_hole_value());
|
| - }
|
| DeoptimizeIf(not_equal, env);
|
|
|
| __ bind(&convert);
|
| @@ -5284,22 +5217,20 @@ void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
|
| void LCodeGen::EmitNumberUntagD(Register input_reg,
|
| Register temp_reg,
|
| XMMRegister result_reg,
|
| - bool allow_undefined_as_nan,
|
| + bool can_convert_undefined_to_nan,
|
| bool deoptimize_on_minus_zero,
|
| LEnvironment* env,
|
| NumberUntagDMode mode) {
|
| Label load_smi, done;
|
|
|
| - STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
|
| - NUMBER_CANDIDATE_IS_ANY_TAGGED);
|
| - if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
|
| + 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 (!allow_undefined_as_nan) {
|
| + if (!can_convert_undefined_to_nan) {
|
| DeoptimizeIf(not_equal, env);
|
| } else {
|
| Label heap_number, convert;
|
| @@ -5307,10 +5238,6 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
|
|
|
| // Convert undefined (and hole) to NaN.
|
| __ cmp(input_reg, factory()->undefined_value());
|
| - if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
|
| - __ j(equal, &convert, Label::kNear);
|
| - __ cmp(input_reg, factory()->the_hole_value());
|
| - }
|
| DeoptimizeIf(not_equal, env);
|
|
|
| __ bind(&convert);
|
| @@ -5438,12 +5365,14 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
|
|
|
|
| void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
|
| - class DeferredTaggedToI: public LDeferredCode {
|
| + class DeferredTaggedToI V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual void Generate() V8_OVERRIDE {
|
| + codegen()->DoDeferredTaggedToI(instr_);
|
| + }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LTaggedToI* instr_;
|
| };
|
| @@ -5597,12 +5526,14 @@ void LCodeGen::DoDeferredTaggedToINoSSE2(LTaggedToINoSSE2* instr) {
|
|
|
|
|
| void LCodeGen::DoTaggedToINoSSE2(LTaggedToINoSSE2* instr) {
|
| - class DeferredTaggedToINoSSE2: public LDeferredCode {
|
| + class DeferredTaggedToINoSSE2 V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredTaggedToINoSSE2(LCodeGen* codegen, LTaggedToINoSSE2* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() { codegen()->DoDeferredTaggedToINoSSE2(instr_); }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual void Generate() V8_OVERRIDE {
|
| + codegen()->DoDeferredTaggedToINoSSE2(instr_);
|
| + }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LTaggedToINoSSE2* instr_;
|
| };
|
| @@ -5635,16 +5566,9 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
|
| instr->hydrogen()->deoptimize_on_minus_zero();
|
| Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg;
|
|
|
| - NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
|
| HValue* value = instr->hydrogen()->value();
|
| - if (value->representation().IsSmi()) {
|
| - mode = NUMBER_CANDIDATE_IS_SMI;
|
| - } else if (value->IsLoadKeyed()) {
|
| - HLoadKeyed* load = HLoadKeyed::cast(value);
|
| - if (load->UsesMustHandleHole()) {
|
| - mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
|
| - }
|
| - }
|
| + NumberUntagDMode mode = value->representation().IsSmi()
|
| + ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
|
|
|
| if (CpuFeatures::IsSupported(SSE2)) {
|
| CpuFeatureScope scope(masm(), SSE2);
|
| @@ -5652,7 +5576,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
|
| EmitNumberUntagD(input_reg,
|
| temp_reg,
|
| result_reg,
|
| - instr->hydrogen()->allow_undefined_as_nan(),
|
| + instr->hydrogen()->can_convert_undefined_to_nan(),
|
| deoptimize_on_minus_zero,
|
| instr->environment(),
|
| mode);
|
| @@ -5660,7 +5584,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
|
| EmitNumberUntagDNoSSE2(input_reg,
|
| temp_reg,
|
| ToX87Register(instr->result()),
|
| - instr->hydrogen()->allow_undefined_as_nan(),
|
| + instr->hydrogen()->can_convert_undefined_to_nan(),
|
| deoptimize_on_minus_zero,
|
| instr->environment(),
|
| mode);
|
| @@ -5673,44 +5597,75 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
| ASSERT(input->IsDoubleRegister());
|
| LOperand* result = instr->result();
|
| ASSERT(result->IsRegister());
|
| - CpuFeatureScope scope(masm(), SSE2);
|
| -
|
| - XMMRegister input_reg = ToDoubleRegister(input);
|
| Register result_reg = ToRegister(result);
|
|
|
| - __ cvttsd2si(result_reg, Operand(input_reg));
|
| + Label done;
|
| + if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
|
| + CpuFeatureScope scope(masm(), SSE2);
|
| +
|
| + XMMRegister input_reg = ToDoubleRegister(input);
|
|
|
| - if (instr->truncating()) {
|
| - // Performs a truncating conversion of a floating point number as used by
|
| - // the JS bitwise operations.
|
| - Label fast_case_succeeded;
|
| - __ cmp(result_reg, 0x80000000u);
|
| - __ j(not_equal, &fast_case_succeeded);
|
| - __ sub(esp, Immediate(kDoubleSize));
|
| - __ movdbl(MemOperand(esp, 0), input_reg);
|
| - DoubleToIStub stub(esp, result_reg, 0, true);
|
| - __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
|
| - __ add(esp, Immediate(kDoubleSize));
|
| - __ bind(&fast_case_succeeded);
|
| + __ cvttsd2si(result_reg, Operand(input_reg));
|
| +
|
| + if (instr->truncating()) {
|
| + // Performs a truncating conversion of a floating point number as used by
|
| + // the JS bitwise operations.
|
| + Label fast_case_succeeded;
|
| + __ cmp(result_reg, 0x80000000u);
|
| + __ j(not_equal, &fast_case_succeeded);
|
| + __ sub(esp, Immediate(kDoubleSize));
|
| + __ movdbl(MemOperand(esp, 0), input_reg);
|
| + DoubleToIStub stub(esp, result_reg, 0, true);
|
| + __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
|
| + __ add(esp, Immediate(kDoubleSize));
|
| + __ bind(&fast_case_succeeded);
|
| + } else {
|
| + __ cvtsi2sd(xmm0, Operand(result_reg));
|
| + __ ucomisd(xmm0, input_reg);
|
| + DeoptimizeIf(not_equal, instr->environment());
|
| + DeoptimizeIf(parity_even, instr->environment()); // NaN.
|
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + // The integer converted back is equal to the original. We
|
| + // only have to test if we got -0 as an input.
|
| + __ test(result_reg, Operand(result_reg));
|
| + __ j(not_zero, &done, Label::kNear);
|
| + __ movmskpd(result_reg, input_reg);
|
| + // Bit 0 contains the sign of the double in input_reg.
|
| + // If input was positive, we are ok and return 0, otherwise
|
| + // deoptimize.
|
| + __ and_(result_reg, 1);
|
| + DeoptimizeIf(not_zero, instr->environment());
|
| + }
|
| + __ bind(&done);
|
| + }
|
| } else {
|
| - Label done;
|
| - __ cvtsi2sd(xmm0, Operand(result_reg));
|
| - __ ucomisd(xmm0, input_reg);
|
| - DeoptimizeIf(not_equal, instr->environment());
|
| - DeoptimizeIf(parity_even, instr->environment()); // NaN.
|
| + X87Register input_reg = ToX87Register(input);
|
| + __ push(result_reg);
|
| + X87Mov(Operand(esp, 0), input_reg, kX87IntOperand);
|
| + if (instr->truncating()) {
|
| + __ pop(result_reg);
|
| + } else {
|
| + X87Fxch(input_reg);
|
| + __ fld(0);
|
| + __ fild_s(Operand(esp, 0));
|
| + __ pop(result_reg);
|
| + __ FCmp();
|
| + DeoptimizeIf(not_equal, instr->environment());
|
| + DeoptimizeIf(parity_even, instr->environment()); // NaN.
|
| + }
|
| if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - // The integer converted back is equal to the original. We
|
| - // only have to test if we got -0 as an input.
|
| __ test(result_reg, Operand(result_reg));
|
| __ j(not_zero, &done, Label::kNear);
|
| - __ movmskpd(result_reg, input_reg);
|
| - // Bit 0 contains the sign of the double in input_reg.
|
| - // If input was positive, we are ok and return 0, otherwise
|
| - // deoptimize.
|
| - __ and_(result_reg, 1);
|
| + // To check for minus zero, we load the value again as float, and check
|
| + // if that is still 0.
|
| + X87Fxch(input_reg);
|
| + __ push(result_reg);
|
| + __ fst_s(Operand(esp, 0));
|
| + __ pop(result_reg);
|
| + __ test(result_reg, Operand(result_reg));
|
| DeoptimizeIf(not_zero, instr->environment());
|
| + __ bind(&done);
|
| }
|
| - __ bind(&done);
|
| }
|
| }
|
|
|
| @@ -5720,30 +5675,56 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
|
| ASSERT(input->IsDoubleRegister());
|
| LOperand* result = instr->result();
|
| ASSERT(result->IsRegister());
|
| - CpuFeatureScope scope(masm(), SSE2);
|
| -
|
| - XMMRegister input_reg = ToDoubleRegister(input);
|
| Register result_reg = ToRegister(result);
|
|
|
| Label done;
|
| - __ cvttsd2si(result_reg, Operand(input_reg));
|
| - __ cvtsi2sd(xmm0, Operand(result_reg));
|
| - __ ucomisd(xmm0, input_reg);
|
| - DeoptimizeIf(not_equal, instr->environment());
|
| - DeoptimizeIf(parity_even, instr->environment()); // NaN.
|
| + if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
|
| + CpuFeatureScope scope(masm(), SSE2);
|
|
|
| - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - // The integer converted back is equal to the original. We
|
| - // only have to test if we got -0 as an input.
|
| - __ test(result_reg, Operand(result_reg));
|
| - __ j(not_zero, &done, Label::kNear);
|
| - __ movmskpd(result_reg, input_reg);
|
| - // Bit 0 contains the sign of the double in input_reg.
|
| - // If input was positive, we are ok and return 0, otherwise
|
| - // deoptimize.
|
| - __ and_(result_reg, 1);
|
| - DeoptimizeIf(not_zero, instr->environment());
|
| - __ bind(&done);
|
| + XMMRegister input_reg = ToDoubleRegister(input);
|
| +
|
| + __ cvttsd2si(result_reg, Operand(input_reg));
|
| + __ cvtsi2sd(xmm0, Operand(result_reg));
|
| + __ ucomisd(xmm0, input_reg);
|
| + DeoptimizeIf(not_equal, instr->environment());
|
| + DeoptimizeIf(parity_even, instr->environment()); // NaN.
|
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + // The integer converted back is equal to the original. We
|
| + // only have to test if we got -0 as an input.
|
| + __ test(result_reg, Operand(result_reg));
|
| + __ j(not_zero, &done, Label::kNear);
|
| + __ movmskpd(result_reg, input_reg);
|
| + // Bit 0 contains the sign of the double in input_reg.
|
| + // If input was positive, we are ok and return 0, otherwise
|
| + // deoptimize.
|
| + __ and_(result_reg, 1);
|
| + DeoptimizeIf(not_zero, instr->environment());
|
| + __ bind(&done);
|
| + }
|
| + } else {
|
| + X87Register input_reg = ToX87Register(input);
|
| + X87Fxch(input_reg);
|
| + __ push(result_reg);
|
| + X87Mov(Operand(esp, 0), input_reg, kX87IntOperand);
|
| + __ fld(0);
|
| + __ fild_s(Operand(esp, 0));
|
| + __ pop(result_reg);
|
| + __ FCmp();
|
| + DeoptimizeIf(not_equal, instr->environment());
|
| + DeoptimizeIf(parity_even, instr->environment()); // NaN.
|
| +
|
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + __ test(result_reg, Operand(result_reg));
|
| + __ j(not_zero, &done, Label::kNear);
|
| + // To check for minus zero, we load the value again as float, and check
|
| + // if that is still 0.
|
| + __ push(result_reg);
|
| + __ fst_s(Operand(esp, 0));
|
| + __ pop(result_reg);
|
| + __ test(result_reg, Operand(result_reg));
|
| + DeoptimizeIf(not_zero, instr->environment());
|
| + __ bind(&done);
|
| + }
|
| }
|
| __ SmiTag(result_reg);
|
| DeoptimizeIf(overflow, instr->environment());
|
| @@ -5841,17 +5822,17 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
|
|
|
|
|
| void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
|
| - class DeferredCheckMaps: public LDeferredCode {
|
| + class DeferredCheckMaps V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
|
| : LDeferredCode(codegen), instr_(instr), object_(object) {
|
| SetExit(check_maps());
|
| }
|
| - virtual void Generate() {
|
| + virtual void Generate() V8_OVERRIDE {
|
| codegen()->DoDeferredInstanceMigration(instr_, object_);
|
| }
|
| Label* check_maps() { return &check_maps_; }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LCheckMaps* instr_;
|
| Label check_maps_;
|
| @@ -6064,12 +6045,14 @@ void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
|
|
|
|
|
| void LCodeGen::DoAllocate(LAllocate* instr) {
|
| - class DeferredAllocate: public LDeferredCode {
|
| + class DeferredAllocate V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() { codegen()->DoDeferredAllocate(instr_); }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual void Generate() V8_OVERRIDE {
|
| + codegen()->DoDeferredAllocate(instr_);
|
| + }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LAllocate* instr_;
|
| };
|
| @@ -6390,6 +6373,7 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
|
| if (info()->IsStub() && type == Deoptimizer::EAGER) {
|
| type = Deoptimizer::LAZY;
|
| }
|
| + Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
|
| DeoptimizeIf(no_condition, instr->environment(), type);
|
| }
|
|
|
| @@ -6412,12 +6396,14 @@ void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
|
|
|
|
|
| void LCodeGen::DoStackCheck(LStackCheck* instr) {
|
| - class DeferredStackCheck: public LDeferredCode {
|
| + class DeferredStackCheck V8_FINAL : public LDeferredCode {
|
| public:
|
| DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
|
| - virtual LInstruction* instr() { return instr_; }
|
| + virtual void Generate() V8_OVERRIDE {
|
| + codegen()->DoDeferredStackCheck(instr_);
|
| + }
|
| + virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
|
| private:
|
| LStackCheck* instr_;
|
| };
|
|
|