| Index: src/ia32/lithium-codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/lithium-codegen-ia32.cc (revision 6437)
|
| +++ src/ia32/lithium-codegen-ia32.cc (working copy)
|
| @@ -1285,11 +1285,11 @@
|
|
|
| NearLabel done;
|
| Condition cc = TokenToCondition(instr->op(), instr->is_double());
|
| - __ mov(ToRegister(result), Handle<Object>(Heap::true_value()));
|
| + __ mov(ToRegister(result), Factory::true_value());
|
| __ j(cc, &done);
|
|
|
| __ bind(&unordered);
|
| - __ mov(ToRegister(result), Handle<Object>(Heap::false_value()));
|
| + __ mov(ToRegister(result), Factory::false_value());
|
| __ bind(&done);
|
| }
|
|
|
| @@ -1320,10 +1320,10 @@
|
| Register result = ToRegister(instr->result());
|
|
|
| __ cmp(left, Operand(right));
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
| NearLabel done;
|
| __ j(equal, &done);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ bind(&done);
|
| }
|
|
|
| @@ -1348,10 +1348,10 @@
|
|
|
| __ cmp(reg, Factory::null_value());
|
| if (instr->is_strict()) {
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
| NearLabel done;
|
| __ j(equal, &done);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ bind(&done);
|
| } else {
|
| NearLabel true_value, false_value, done;
|
| @@ -1368,10 +1368,10 @@
|
| __ test(scratch, Immediate(1 << Map::kIsUndetectable));
|
| __ j(not_zero, &true_value);
|
| __ bind(&false_value);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ jmp(&done);
|
| __ bind(&true_value);
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
| __ bind(&done);
|
| }
|
| }
|
| @@ -1447,11 +1447,11 @@
|
| __ j(true_cond, &is_true);
|
|
|
| __ bind(&is_false);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ jmp(&done);
|
|
|
| __ bind(&is_true);
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
|
|
| __ bind(&done);
|
| }
|
| @@ -1479,10 +1479,10 @@
|
|
|
| ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
| __ test(input, Immediate(kSmiTagMask));
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
| NearLabel done;
|
| __ j(zero, &done);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ bind(&done);
|
| }
|
|
|
| @@ -1507,7 +1507,6 @@
|
| }
|
|
|
|
|
| -
|
| static Condition BranchCondition(HHasInstanceType* instr) {
|
| InstanceType from = instr->from();
|
| InstanceType to = instr->to();
|
| @@ -1529,10 +1528,10 @@
|
| __ j(zero, &is_false);
|
| __ CmpObjectType(input, TestType(instr->hydrogen()), result);
|
| __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false);
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
| __ jmp(&done);
|
| __ bind(&is_false);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ bind(&done);
|
| }
|
|
|
| @@ -1559,12 +1558,12 @@
|
| Register result = ToRegister(instr->result());
|
|
|
| ASSERT(instr->hydrogen()->value()->representation().IsTagged());
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
| __ test(FieldOperand(input, String::kHashFieldOffset),
|
| Immediate(String::kContainsCachedArrayIndexMask));
|
| NearLabel done;
|
| __ j(not_zero, &done);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ bind(&done);
|
| }
|
|
|
| @@ -1653,11 +1652,11 @@
|
| __ j(not_equal, &is_false);
|
|
|
| __ bind(&is_true);
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
| __ jmp(&done);
|
|
|
| __ bind(&is_false);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ bind(&done);
|
| }
|
|
|
| @@ -2221,11 +2220,12 @@
|
|
|
| Label negative;
|
| __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
|
| - // Check the sign of the argument. If the argument is positive,
|
| - // just return it.
|
| + // Check the sign of the argument. If the argument is positive, just
|
| + // return it. We do not need to patch the stack since |input| and
|
| + // |result| are the same register and |input| will be restored
|
| + // unchanged by popping safepoint registers.
|
| __ test(tmp, Immediate(HeapNumber::kSignMask));
|
| __ j(not_zero, &negative);
|
| - __ mov(tmp, input_reg);
|
| __ jmp(&done);
|
|
|
| __ bind(&negative);
|
| @@ -2252,14 +2252,25 @@
|
| __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
|
| __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
|
| __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
|
| + __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp);
|
|
|
| __ bind(&done);
|
| - __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp);
|
| -
|
| __ PopSafepointRegisters();
|
| }
|
|
|
|
|
| +void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
|
| + Register input_reg = ToRegister(instr->InputAt(0));
|
| + __ test(input_reg, Operand(input_reg));
|
| + Label is_positive;
|
| + __ j(not_sign, &is_positive);
|
| + __ neg(input_reg);
|
| + __ test(input_reg, Operand(input_reg));
|
| + DeoptimizeIf(negative, instr->environment());
|
| + __ bind(&is_positive);
|
| +}
|
| +
|
| +
|
| void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
|
| // Class for deferred case.
|
| class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
|
| @@ -2284,31 +2295,15 @@
|
| __ subsd(scratch, input_reg);
|
| __ pand(input_reg, scratch);
|
| } else if (r.IsInteger32()) {
|
| - Register input_reg = ToRegister(instr->InputAt(0));
|
| - __ test(input_reg, Operand(input_reg));
|
| - Label is_positive;
|
| - __ j(not_sign, &is_positive);
|
| - __ neg(input_reg);
|
| - __ test(input_reg, Operand(input_reg));
|
| - DeoptimizeIf(negative, instr->environment());
|
| - __ bind(&is_positive);
|
| + EmitIntegerMathAbs(instr);
|
| } else { // Tagged case.
|
| DeferredMathAbsTaggedHeapNumber* deferred =
|
| new DeferredMathAbsTaggedHeapNumber(this, instr);
|
| - Label not_smi;
|
| Register input_reg = ToRegister(instr->InputAt(0));
|
| // Smi check.
|
| __ test(input_reg, Immediate(kSmiTagMask));
|
| __ j(not_zero, deferred->entry());
|
| - __ test(input_reg, Operand(input_reg));
|
| - Label is_positive;
|
| - __ j(not_sign, &is_positive);
|
| - __ neg(input_reg);
|
| -
|
| - __ test(input_reg, Operand(input_reg));
|
| - DeoptimizeIf(negative, instr->environment());
|
| -
|
| - __ bind(&is_positive);
|
| + EmitIntegerMathAbs(instr);
|
| __ bind(deferred->exit());
|
| }
|
| }
|
| @@ -2651,6 +2646,151 @@
|
| }
|
|
|
|
|
| +void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
| + class DeferredStringCharCodeAt: public LDeferredCode {
|
| + public:
|
| + DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
|
| + : LDeferredCode(codegen), instr_(instr) { }
|
| + virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
|
| + private:
|
| + LStringCharCodeAt* instr_;
|
| + };
|
| +
|
| + Register string = ToRegister(instr->string());
|
| + Register index = no_reg;
|
| + int const_index = -1;
|
| + if (instr->index()->IsConstantOperand()) {
|
| + const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
| + STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
|
| + if (!Smi::IsValid(const_index)) {
|
| + // Guaranteed to be out of bounds because of the assert above.
|
| + // So the bounds check that must dominate this instruction must
|
| + // have deoptimized already.
|
| + if (FLAG_debug_code) {
|
| + __ Abort("StringCharCodeAt: out of bounds index.");
|
| + }
|
| + // No code needs to be generated.
|
| + return;
|
| + }
|
| + } else {
|
| + index = ToRegister(instr->index());
|
| + }
|
| + Register result = ToRegister(instr->result());
|
| +
|
| + DeferredStringCharCodeAt* deferred =
|
| + new DeferredStringCharCodeAt(this, instr);
|
| +
|
| + NearLabel flat_string, ascii_string, done;
|
| +
|
| + // Fetch the instance type of the receiver into result register.
|
| + __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
|
| + __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
|
| +
|
| + // We need special handling for non-flat strings.
|
| + STATIC_ASSERT(kSeqStringTag == 0);
|
| + __ test(result, Immediate(kStringRepresentationMask));
|
| + __ j(zero, &flat_string);
|
| +
|
| + // Handle non-flat strings.
|
| + __ test(result, Immediate(kIsConsStringMask));
|
| + __ j(zero, deferred->entry());
|
| +
|
| + // ConsString.
|
| + // Check whether the right hand side is the empty string (i.e. if
|
| + // this is really a flat string in a cons string). If that is not
|
| + // the case we would rather go to the runtime system now to flatten
|
| + // the string.
|
| + __ cmp(FieldOperand(string, ConsString::kSecondOffset),
|
| + Immediate(Factory::empty_string()));
|
| + __ j(not_equal, deferred->entry());
|
| + // Get the first of the two strings and load its instance type.
|
| + __ mov(string, FieldOperand(string, ConsString::kFirstOffset));
|
| + __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
|
| + __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
|
| + // If the first cons component is also non-flat, then go to runtime.
|
| + STATIC_ASSERT(kSeqStringTag == 0);
|
| + __ test(result, Immediate(kStringRepresentationMask));
|
| + __ j(not_zero, deferred->entry());
|
| +
|
| + // Check for 1-byte or 2-byte string.
|
| + __ bind(&flat_string);
|
| + STATIC_ASSERT(kAsciiStringTag != 0);
|
| + __ test(result, Immediate(kStringEncodingMask));
|
| + __ j(not_zero, &ascii_string);
|
| +
|
| + // 2-byte string.
|
| + // Load the 2-byte character code into the result register.
|
| + STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
| + if (instr->index()->IsConstantOperand()) {
|
| + __ movzx_w(result,
|
| + FieldOperand(string,
|
| + SeqTwoByteString::kHeaderSize + 2 * const_index));
|
| + } else {
|
| + __ movzx_w(result, FieldOperand(string,
|
| + index,
|
| + times_2,
|
| + SeqTwoByteString::kHeaderSize));
|
| + }
|
| + __ jmp(&done);
|
| +
|
| + // ASCII string.
|
| + // Load the byte into the result register.
|
| + __ bind(&ascii_string);
|
| + if (instr->index()->IsConstantOperand()) {
|
| + __ movzx_b(result, FieldOperand(string,
|
| + SeqAsciiString::kHeaderSize + const_index));
|
| + } else {
|
| + __ movzx_b(result, FieldOperand(string,
|
| + index,
|
| + times_1,
|
| + SeqAsciiString::kHeaderSize));
|
| + }
|
| + __ bind(&done);
|
| + __ bind(deferred->exit());
|
| +}
|
| +
|
| +
|
| +void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
|
| + Register string = ToRegister(instr->string());
|
| + Register result = ToRegister(instr->result());
|
| +
|
| + // TODO(3095996): Get rid of this. For now, we need to make the
|
| + // result register contain a valid pointer because it is already
|
| + // contained in the register pointer map.
|
| + __ Set(result, Immediate(0));
|
| +
|
| + __ PushSafepointRegisters();
|
| + __ push(string);
|
| + // Push the index as a smi. This is safe because of the checks in
|
| + // DoStringCharCodeAt above.
|
| + STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
|
| + if (instr->index()->IsConstantOperand()) {
|
| + int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
| + __ push(Immediate(Smi::FromInt(const_index)));
|
| + } else {
|
| + Register index = ToRegister(instr->index());
|
| + __ SmiTag(index);
|
| + __ push(index);
|
| + }
|
| + __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
|
| + RecordSafepointWithRegisters(
|
| + instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
|
| + if (FLAG_debug_code) {
|
| + __ AbortIfNotSmi(eax);
|
| + }
|
| + __ SmiUntag(eax);
|
| + __ mov(Operand(esp, EspIndexForPushAll(result) * kPointerSize), eax);
|
| + __ PopSafepointRegisters();
|
| +}
|
| +
|
| +
|
| +void LCodeGen::DoStringLength(LStringLength* instr) {
|
| + Register string = ToRegister(instr->string());
|
| + Register result = ToRegister(instr->result());
|
| + __ mov(result, FieldOperand(string, String::kLengthOffset));
|
| +}
|
| +
|
| +
|
| void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
|
| LOperand* input = instr->InputAt(0);
|
| ASSERT(input->IsRegister() || input->IsStackSlot());
|
| @@ -3077,13 +3217,19 @@
|
| InstanceType last = instr->hydrogen()->last();
|
|
|
| __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
|
| - __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
|
| - static_cast<int8_t>(first));
|
|
|
| // If there is only one type in the interval check for equality.
|
| if (first == last) {
|
| + __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
|
| + static_cast<int8_t>(first));
|
| DeoptimizeIf(not_equal, instr->environment());
|
| - } else {
|
| + } else if (first == FIRST_STRING_TYPE && last == LAST_STRING_TYPE) {
|
| + // String has a dedicated bit in instance type.
|
| + __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), kIsNotStringMask);
|
| + DeoptimizeIf(not_zero, instr->environment());
|
| + } else {
|
| + __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
|
| + static_cast<int8_t>(first));
|
| DeoptimizeIf(below, instr->environment());
|
| // Omit check for the last type.
|
| if (last != LAST_TYPE) {
|
| @@ -3292,11 +3438,11 @@
|
| instr->type_literal());
|
| __ j(final_branch_condition, &true_label);
|
| __ bind(&false_label);
|
| - __ mov(result, Handle<Object>(Heap::false_value()));
|
| + __ mov(result, Factory::false_value());
|
| __ jmp(&done);
|
|
|
| __ bind(&true_label);
|
| - __ mov(result, Handle<Object>(Heap::true_value()));
|
| + __ mov(result, Factory::true_value());
|
|
|
| __ bind(&done);
|
| }
|
| @@ -3341,9 +3487,9 @@
|
| final_branch_condition = below;
|
|
|
| } else if (type_name->Equals(Heap::boolean_symbol())) {
|
| - __ cmp(input, Handle<Object>(Heap::true_value()));
|
| + __ cmp(input, Factory::true_value());
|
| __ j(equal, true_label);
|
| - __ cmp(input, Handle<Object>(Heap::false_value()));
|
| + __ cmp(input, Factory::false_value());
|
| final_branch_condition = equal;
|
|
|
| } else if (type_name->Equals(Heap::undefined_symbol())) {
|
|
|