| Index: src/arm/lithium-codegen-arm.cc
|
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
|
| index 9ec80f819a062dbf3078fc4a0487b765177a19cb..e5baef2503ab62c5c4434db9a8c001c6d5a3f5fd 100644
|
| --- a/src/arm/lithium-codegen-arm.cc
|
| +++ b/src/arm/lithium-codegen-arm.cc
|
| @@ -417,72 +417,12 @@ Register LCodeGen::ToRegister(LOperand* op) const {
|
| }
|
|
|
|
|
| -Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
|
| - if (op->IsRegister()) {
|
| - return ToRegister(op->index());
|
| - } else if (op->IsConstantOperand()) {
|
| - LConstantOperand* const_op = LConstantOperand::cast(op);
|
| - HConstant* constant = chunk_->LookupConstant(const_op);
|
| - Handle<Object> literal = constant->handle();
|
| - Representation r = chunk_->LookupLiteralRepresentation(const_op);
|
| - if (r.IsInteger32()) {
|
| - ASSERT(literal->IsNumber());
|
| - __ mov(scratch, Operand(static_cast<int32_t>(literal->Number())));
|
| - } else if (r.IsDouble()) {
|
| - Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
|
| - } else {
|
| - ASSERT(r.IsTagged());
|
| - __ LoadObject(scratch, literal);
|
| - }
|
| - return scratch;
|
| - } else if (op->IsStackSlot() || op->IsArgument()) {
|
| - __ ldr(scratch, ToMemOperand(op));
|
| - return scratch;
|
| - }
|
| - UNREACHABLE();
|
| - return scratch;
|
| -}
|
| -
|
| -
|
| DwVfpRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
|
| ASSERT(op->IsDoubleRegister());
|
| return ToDoubleRegister(op->index());
|
| }
|
|
|
|
|
| -DwVfpRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
|
| - SwVfpRegister flt_scratch,
|
| - DwVfpRegister dbl_scratch) {
|
| - if (op->IsDoubleRegister()) {
|
| - return ToDoubleRegister(op->index());
|
| - } else if (op->IsConstantOperand()) {
|
| - LConstantOperand* const_op = LConstantOperand::cast(op);
|
| - HConstant* constant = chunk_->LookupConstant(const_op);
|
| - Handle<Object> literal = constant->handle();
|
| - Representation r = chunk_->LookupLiteralRepresentation(const_op);
|
| - if (r.IsInteger32()) {
|
| - ASSERT(literal->IsNumber());
|
| - __ mov(ip, Operand(static_cast<int32_t>(literal->Number())));
|
| - __ vmov(flt_scratch, ip);
|
| - __ vcvt_f64_s32(dbl_scratch, flt_scratch);
|
| - return dbl_scratch;
|
| - } else if (r.IsDouble()) {
|
| - Abort(kUnsupportedDoubleImmediate);
|
| - } else if (r.IsTagged()) {
|
| - Abort(kUnsupportedTaggedImmediate);
|
| - }
|
| - } else if (op->IsStackSlot() || op->IsArgument()) {
|
| - // TODO(regis): Why is vldr not taking a MemOperand?
|
| - // __ vldr(dbl_scratch, ToMemOperand(op));
|
| - MemOperand mem_op = ToMemOperand(op);
|
| - __ vldr(dbl_scratch, mem_op.rn(), mem_op.offset());
|
| - return dbl_scratch;
|
| - }
|
| - UNREACHABLE();
|
| - return dbl_scratch;
|
| -}
|
| -
|
| -
|
| Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
|
| HConstant* constant = chunk_->LookupConstant(op);
|
| ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
|
| @@ -1368,7 +1308,8 @@ void LCodeGen::EmitSignedIntegerDivisionByConstant(
|
|
|
| void LCodeGen::DoDivI(LDivI* instr) {
|
| if (instr->hydrogen()->HasPowerOf2Divisor()) {
|
| - Register dividend = ToRegister(instr->left());
|
| + const Register dividend = ToRegister(instr->left());
|
| + const Register result = ToRegister(instr->result());
|
| int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant();
|
| int32_t test_value = 0;
|
| int32_t power = 0;
|
| @@ -1379,7 +1320,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
| } else {
|
| // Check for (0 / -x) that will produce negative zero.
|
| if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - __ tst(dividend, Operand(dividend));
|
| + __ cmp(dividend, Operand::Zero());
|
| DeoptimizeIf(eq, instr->environment());
|
| }
|
| // Check for (kMinInt / -1).
|
| @@ -1394,19 +1335,22 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
| if (test_value != 0) {
|
| if (instr->hydrogen()->CheckFlag(
|
| HInstruction::kAllUsesTruncatingToInt32)) {
|
| - __ cmp(dividend, Operand(0));
|
| - __ rsb(dividend, dividend, Operand(0), LeaveCC, lt);
|
| - __ mov(dividend, Operand(dividend, ASR, power));
|
| - if (divisor > 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, lt);
|
| + __ sub(result, dividend, Operand::Zero(), SetCC);
|
| + __ rsb(result, result, Operand::Zero(), LeaveCC, lt);
|
| + __ mov(result, Operand(result, ASR, power));
|
| + if (divisor > 0) __ rsb(result, result, Operand::Zero(), LeaveCC, lt);
|
| return; // Don't fall through to "__ rsb" below.
|
| } else {
|
| // Deoptimize if remainder is not 0.
|
| __ tst(dividend, Operand(test_value));
|
| DeoptimizeIf(ne, instr->environment());
|
| - __ mov(dividend, Operand(dividend, ASR, power));
|
| + __ mov(result, Operand(dividend, ASR, power));
|
| }
|
| + } else {
|
| + __ Move(result, dividend);
|
| }
|
| - if (divisor < 0) __ rsb(dividend, dividend, Operand(0));
|
| +
|
| + if (divisor < 0) __ rsb(result, result, Operand::Zero());
|
|
|
| return;
|
| }
|
| @@ -1572,17 +1516,15 @@ void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
|
|
|
|
|
| void LCodeGen::DoMulI(LMulI* instr) {
|
| - Register scratch = scratch0();
|
| Register result = ToRegister(instr->result());
|
| // Note that result may alias left.
|
| Register left = ToRegister(instr->left());
|
| LOperand* right_op = instr->right();
|
|
|
| - bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
|
| bool bailout_on_minus_zero =
|
| instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
|
|
|
| - if (right_op->IsConstantOperand() && !can_overflow) {
|
| + if (right_op->IsConstantOperand()) {
|
| // Use optimized code for specific constants.
|
| int32_t constant = ToRepresentation(
|
| LConstantOperand::cast(right_op),
|
| @@ -1643,12 +1585,11 @@ void LCodeGen::DoMulI(LMulI* instr) {
|
| }
|
|
|
| } else {
|
| - Register right = EmitLoadRegister(right_op, scratch);
|
| - if (bailout_on_minus_zero) {
|
| - __ orr(ToRegister(instr->temp()), left, right);
|
| - }
|
| + ASSERT(right_op->IsRegister());
|
| + Register right = ToRegister(right_op);
|
|
|
| - if (can_overflow) {
|
| + if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
|
| + Register scratch = scratch0();
|
| // scratch:result = left * right.
|
| if (instr->hydrogen()->representation().IsSmi()) {
|
| __ SmiUntag(result, left);
|
| @@ -1668,12 +1609,12 @@ void LCodeGen::DoMulI(LMulI* instr) {
|
| }
|
|
|
| if (bailout_on_minus_zero) {
|
| - // Bail out if the result is supposed to be negative zero.
|
| Label done;
|
| + __ teq(left, Operand(right));
|
| + __ b(pl, &done);
|
| + // Bail out if the result is minus zero.
|
| __ cmp(result, Operand::Zero());
|
| - __ b(ne, &done);
|
| - __ cmp(ToRegister(instr->temp()), Operand::Zero());
|
| - DeoptimizeIf(mi, instr->environment());
|
| + DeoptimizeIf(eq, instr->environment());
|
| __ bind(&done);
|
| }
|
| }
|
| @@ -1686,32 +1627,40 @@ void LCodeGen::DoBitI(LBitI* instr) {
|
| ASSERT(left_op->IsRegister());
|
| Register left = ToRegister(left_op);
|
| Register result = ToRegister(instr->result());
|
| - Operand right(no_reg);
|
|
|
| - if (right_op->IsStackSlot() || right_op->IsArgument()) {
|
| - right = Operand(EmitLoadRegister(right_op, ip));
|
| + if (right_op->IsStackSlot()) {
|
| + MemOperand right(ToMemOperand(right_op));
|
| + switch (instr->op()) {
|
| + case Token::BIT_AND:
|
| + __ AndMemOperand(result, left, right);
|
| + break;
|
| + case Token::BIT_OR:
|
| + __ OrrMemOperand(result, left, right);
|
| + break;
|
| + case Token::BIT_XOR:
|
| + __ EorMemOperand(result, left, right);
|
| + break;
|
| + default: UNREACHABLE();
|
| + }
|
| } else {
|
| - ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
|
| - right = ToOperand(right_op);
|
| - }
|
| -
|
| - switch (instr->op()) {
|
| - case Token::BIT_AND:
|
| - __ and_(result, left, right);
|
| - break;
|
| - case Token::BIT_OR:
|
| - __ orr(result, left, right);
|
| - break;
|
| - case Token::BIT_XOR:
|
| - if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
|
| - __ mvn(result, Operand(left));
|
| - } else {
|
| - __ eor(result, left, right);
|
| - }
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - break;
|
| + Operand right(ToOperand(right_op));
|
| + switch (instr->op()) {
|
| + case Token::BIT_AND:
|
| + __ and_(result, left, right);
|
| + break;
|
| + case Token::BIT_OR:
|
| + __ orr(result, left, right);
|
| + break;
|
| + case Token::BIT_XOR:
|
| + if (right_op->IsConstantOperand()
|
| + && right.immediate() == int32_t(~0)) {
|
| + __ mvn(result, Operand(left));
|
| + } else {
|
| + __ eor(result, left, right);
|
| + }
|
| + break;
|
| + default: UNREACHABLE();
|
| + }
|
| }
|
| }
|
|
|
| @@ -1805,18 +1754,17 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
|
|
|
|
|
| void LCodeGen::DoSubI(LSubI* instr) {
|
| - LOperand* left = instr->left();
|
| - LOperand* right = instr->right();
|
| - LOperand* result = instr->result();
|
| + Register left = ToRegister(instr->left());
|
| + LOperand* right_op = instr->right();
|
| + Register result = ToRegister(instr->result());
|
| bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
|
| SBit set_cond = can_overflow ? SetCC : LeaveCC;
|
|
|
| - if (right->IsStackSlot() || right->IsArgument()) {
|
| - Register right_reg = EmitLoadRegister(right, ip);
|
| - __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
|
| + if (right_op->IsStackSlot()) {
|
| + __ SubMemOperand(result, left, ToMemOperand(right_op), set_cond);
|
| } else {
|
| - ASSERT(right->IsRegister() || right->IsConstantOperand());
|
| - __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
|
| + ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
|
| + __ sub(result, left, ToOperand(right_op), set_cond);
|
| }
|
|
|
| if (can_overflow) {
|
| @@ -1826,18 +1774,16 @@ void LCodeGen::DoSubI(LSubI* instr) {
|
|
|
|
|
| void LCodeGen::DoRSubI(LRSubI* instr) {
|
| - LOperand* left = instr->left();
|
| - LOperand* right = instr->right();
|
| - LOperand* result = instr->result();
|
| + Register left = ToRegister(instr->left());
|
| + LOperand* right_op = instr->right();
|
| + Register result = ToRegister(instr->result());
|
| bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
|
| SBit set_cond = can_overflow ? SetCC : LeaveCC;
|
|
|
| - if (right->IsStackSlot() || right->IsArgument()) {
|
| - Register right_reg = EmitLoadRegister(right, ip);
|
| - __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
|
| + if (right_op->IsStackSlot()) {
|
| + __ RsbMemOperand(result, left, ToMemOperand(right_op), set_cond);
|
| } else {
|
| - ASSERT(right->IsRegister() || right->IsConstantOperand());
|
| - __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
|
| + __ rsb(result, left, ToOperand(right_op), set_cond);
|
| }
|
|
|
| if (can_overflow) {
|
| @@ -1961,38 +1907,50 @@ void LCodeGen::DoDateField(LDateField* instr) {
|
|
|
| void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
|
| Register string = ToRegister(instr->string());
|
| - Register index = ToRegister(instr->index());
|
| Register value = ToRegister(instr->value());
|
| + Register scratch = scratch0();
|
| + LOperand* index_op = instr->index();
|
| String::Encoding encoding = instr->encoding();
|
|
|
| if (FLAG_debug_code) {
|
| - __ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
|
| - __ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
|
| + __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
|
| + __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
|
|
|
| - __ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
|
| + __ and_(scratch, scratch,
|
| + Operand(kStringRepresentationMask | kStringEncodingMask));
|
| static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
|
| static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
|
| - __ cmp(ip, Operand(encoding == String::ONE_BYTE_ENCODING
|
| - ? one_byte_seq_type : two_byte_seq_type));
|
| + __ cmp(scratch, Operand(encoding == String::ONE_BYTE_ENCODING
|
| + ? one_byte_seq_type : two_byte_seq_type));
|
| __ Check(eq, kUnexpectedStringType);
|
| }
|
|
|
| - __ add(ip,
|
| - string,
|
| - Operand(SeqString::kHeaderSize - kHeapObjectTag));
|
| - if (encoding == String::ONE_BYTE_ENCODING) {
|
| - __ strb(value, MemOperand(ip, index));
|
| + if (index_op->IsConstantOperand()) {
|
| + int constant_index = ToInteger32(LConstantOperand::cast(index_op));
|
| + if (encoding == String::ONE_BYTE_ENCODING) {
|
| + __ strb(value,
|
| + FieldMemOperand(string,
|
| + SeqString::kHeaderSize + constant_index));
|
| + } else {
|
| + __ strh(value,
|
| + FieldMemOperand(string,
|
| + SeqString::kHeaderSize + constant_index * 2));
|
| + }
|
| } else {
|
| - // MemOperand with ip as the base register is not allowed for strh, so
|
| - // we do the address calculation explicitly.
|
| - __ add(ip, ip, Operand(index, LSL, 1));
|
| - __ strh(value, MemOperand(ip));
|
| + Register index = ToRegister(index_op);
|
| + if (encoding == String::ONE_BYTE_ENCODING) {
|
| + __ add(scratch, string, Operand(index));
|
| + __ strb(value, FieldMemOperand(scratch, SeqString::kHeaderSize));
|
| + } else {
|
| + __ add(scratch, string, Operand(index, LSL, 1));
|
| + __ strh(value, FieldMemOperand(scratch, SeqString::kHeaderSize));
|
| + }
|
| }
|
| }
|
|
|
|
|
| void LCodeGen::DoThrow(LThrow* instr) {
|
| - Register input_reg = EmitLoadRegister(instr->value(), ip);
|
| + Register input_reg = ToRegister(instr->value());
|
| __ push(input_reg);
|
| CallRuntime(Runtime::kThrow, 1, instr);
|
|
|
| @@ -2003,18 +1961,17 @@ void LCodeGen::DoThrow(LThrow* instr) {
|
|
|
|
|
| void LCodeGen::DoAddI(LAddI* instr) {
|
| - LOperand* left = instr->left();
|
| - LOperand* right = instr->right();
|
| - LOperand* result = instr->result();
|
| + Register left = ToRegister(instr->left());
|
| + LOperand* right_op = instr->right();
|
| + Register result = ToRegister(instr->result());
|
| bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
|
| SBit set_cond = can_overflow ? SetCC : LeaveCC;
|
|
|
| - if (right->IsStackSlot() || right->IsArgument()) {
|
| - Register right_reg = EmitLoadRegister(right, ip);
|
| - __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
|
| + if (right_op->IsStackSlot()) {
|
| + __ AddMemOperand(result, left, ToMemOperand(right_op), set_cond);
|
| } else {
|
| - ASSERT(right->IsRegister() || right->IsConstantOperand());
|
| - __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
|
| + ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
|
| + __ add(result, left, ToOperand(right_op), set_cond);
|
| }
|
|
|
| if (can_overflow) {
|
| @@ -2030,9 +1987,7 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
|
| if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
|
| Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
|
| Register left_reg = ToRegister(left);
|
| - Operand right_op = (right->IsRegister() || right->IsConstantOperand())
|
| - ? ToOperand(right)
|
| - : Operand(EmitLoadRegister(right, ip));
|
| + Operand right_op = ToOperand(right);
|
| Register result_reg = ToRegister(instr->result());
|
| __ cmp(left_reg, right_op);
|
| __ Move(result_reg, left_reg, condition);
|
| @@ -2040,7 +1995,13 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
|
| } else {
|
| ASSERT(instr->hydrogen()->representation().IsDouble());
|
| DwVfpRegister left_reg = ToDoubleRegister(left);
|
| - DwVfpRegister right_reg = ToDoubleRegister(right);
|
| + DwVfpRegister right_reg ;
|
| + if (right->IsDoubleStackSlot()) {
|
| + __ vldr(double_scratch0(), ToMemOperand(right));
|
| + right_reg = double_scratch0();
|
| + } else {
|
| + right_reg = ToDoubleRegister(right);
|
| + }
|
| DwVfpRegister result_reg = ToDoubleRegister(instr->result());
|
| Label result_is_nan, return_left, return_right, check_zero, done;
|
| __ VFPCompareAndSetFlags(left_reg, right_reg);
|
| @@ -2092,7 +2053,14 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
|
|
|
| void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
|
| DwVfpRegister left = ToDoubleRegister(instr->left());
|
| - DwVfpRegister right = ToDoubleRegister(instr->right());
|
| + DwVfpRegister right;
|
| + if (instr->right()->IsDoubleStackSlot()) {
|
| + __ vldr(double_scratch0(), ToMemOperand(instr->right()));
|
| + right = double_scratch0();
|
| + } else {
|
| + ASSERT(instr->right()->IsDoubleRegister());
|
| + right = ToDoubleRegister(instr->right());
|
| + }
|
| DwVfpRegister result = ToDoubleRegister(instr->result());
|
| switch (instr->op()) {
|
| case Token::ADD:
|
| @@ -2520,8 +2488,7 @@ void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
|
|
|
|
|
| void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
|
| - Register input_reg = EmitLoadRegister(instr->value(), ip);
|
| - __ SmiTst(input_reg);
|
| + __ SmiTst(ToRegister(instr->value()));
|
| EmitBranch(instr, eq);
|
| }
|
|
|
| @@ -3146,20 +3113,35 @@ void LCodeGen::DoLoadExternalArrayPointer(
|
| void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
|
| Register arguments = ToRegister(instr->arguments());
|
| Register result = ToRegister(instr->result());
|
| - if (instr->length()->IsConstantOperand() &&
|
| - instr->index()->IsConstantOperand()) {
|
| - int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
| + // There are two words between the frame pointer and the last argument.
|
| + // Subtracting from length accounts for one of them add one more.
|
| + if (instr->length()->IsConstantOperand()) {
|
| int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
|
| - int index = (const_length - const_index) + 1;
|
| - __ ldr(result, MemOperand(arguments, index * kPointerSize));
|
| + if (instr->index()->IsConstantOperand()) {
|
| + int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
| + int index = (const_length - const_index) + 1;
|
| + __ ldr(result, MemOperand(arguments, index * kPointerSize));
|
| + } else {
|
| + Register index = ToRegister(instr->index());
|
| + __ rsb(result, index, Operand(const_length + 1));
|
| + __ ldr(result, MemOperand(arguments, result, LSL, kPointerSizeLog2));
|
| + }
|
| + } else if (instr->index()->IsConstantOperand()) {
|
| + Register length = ToRegister(instr->length());
|
| + int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
| + int loc = const_index - 1;
|
| + if (loc != 0) {
|
| + __ sub(result, length, Operand(loc));
|
| + __ ldr(result, MemOperand(arguments, result, LSL, kPointerSizeLog2));
|
| + } else {
|
| + __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2));
|
| + }
|
| } else {
|
| Register length = ToRegister(instr->length());
|
| Register index = ToRegister(instr->index());
|
| - // There are two words between the frame pointer and the last argument.
|
| - // Subtracting from length accounts for one of them add one more.
|
| - __ sub(length, length, index);
|
| - __ add(length, length, Operand(1));
|
| - __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2));
|
| + __ sub(result, length, index);
|
| + __ add(result, result, Operand(1));
|
| + __ ldr(result, MemOperand(arguments, result, LSL, kPointerSizeLog2));
|
| }
|
| }
|
|
|
| @@ -3253,25 +3235,25 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
|
| int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
|
| int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
|
| ? (element_size_shift - kSmiTagSize) : element_size_shift;
|
| - int constant_key = 0;
|
| if (key_is_constant) {
|
| - constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
|
| + int constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
|
| if (constant_key & 0xF0000000) {
|
| Abort(kArrayIndexConstantValueTooBig);
|
| }
|
| + int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
|
| + ((constant_key + instr->additional_index()) << element_size_shift);
|
| + __ add(scratch, elements, Operand(base_offset));
|
| } else {
|
| + int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
|
| + ((instr->additional_index()) << element_size_shift);
|
| key = ToRegister(instr->key());
|
| + __ add(scratch, elements, Operand(base_offset));
|
| + __ add(scratch, scratch, Operand(key, LSL, shift_size));
|
| }
|
|
|
| - int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
|
| - ((constant_key + instr->additional_index()) << element_size_shift);
|
| - if (!key_is_constant) {
|
| - __ add(elements, elements, Operand(key, LSL, shift_size));
|
| - }
|
| - __ add(elements, elements, Operand(base_offset));
|
| - __ vldr(result, elements, 0);
|
| + __ vldr(result, scratch, 0);
|
| if (instr->hydrogen()->RequiresHoleCheck()) {
|
| - __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
|
| + __ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
|
| __ cmp(scratch, Operand(kHoleNanUpper32));
|
| DeoptimizeIf(eq, instr->environment());
|
| }
|
| @@ -3291,7 +3273,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
|
| instr->additional_index());
|
| store_base = elements;
|
| } else {
|
| - Register key = EmitLoadRegister(instr->key(), scratch0());
|
| + Register key = ToRegister(instr->key());
|
| // Even though the HLoadKeyed instruction forces the input
|
| // representation for the key to be an integer, the input gets replaced
|
| // during bound check elimination with the index argument to the bounds
|
| @@ -3516,13 +3498,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
|
|
|
|
| void LCodeGen::DoPushArgument(LPushArgument* instr) {
|
| - LOperand* argument = instr->value();
|
| - if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
|
| - Abort(kDoPushArgumentNotImplementedForDoubleType);
|
| - } else {
|
| - Register argument_reg = EmitLoadRegister(argument, ip);
|
| - __ push(argument_reg);
|
| - }
|
| + ASSERT(instr->value()->IsRegister());
|
| + __ push(ToRegister(instr->value()));
|
| }
|
|
|
|
|
| @@ -3961,10 +3938,11 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
| DwVfpRegister double_scratch2 = double_scratch0();
|
| Register temp1 = ToRegister(instr->temp1());
|
| Register temp2 = ToRegister(instr->temp2());
|
| + Register temp3 = scratch0();
|
|
|
| MathExpGenerator::EmitMathExp(
|
| masm(), input, result, double_scratch1, double_scratch2,
|
| - temp1, temp2, scratch0());
|
| + temp1, temp2, temp3);
|
| }
|
|
|
|
|
| @@ -4304,16 +4282,23 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
|
|
| if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
|
| elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
|
| + Register address = scratch0();
|
| DwVfpRegister value(ToDoubleRegister(instr->value()));
|
| - Operand operand(key_is_constant
|
| - ? Operand(constant_key << element_size_shift)
|
| - : Operand(key, LSL, shift_size));
|
| - __ add(scratch0(), external_pointer, operand);
|
| + if (key_is_constant) {
|
| + if (constant_key != 0) {
|
| + __ add(address, external_pointer,
|
| + Operand(constant_key << element_size_shift)) ;
|
| + } else {
|
| + address = external_pointer;
|
| + }
|
| + } else {
|
| + __ add(address, external_pointer, Operand(key, LSL, shift_size));
|
| + }
|
| if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
| __ vcvt_f32_f64(double_scratch0().low(), value);
|
| - __ vstr(double_scratch0().low(), scratch0(), additional_offset);
|
| + __ vstr(double_scratch0().low(), address, additional_offset);
|
| } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
|
| - __ vstr(value, scratch0(), additional_offset);
|
| + __ vstr(value, address, additional_offset);
|
| }
|
| } else {
|
| Register value(ToRegister(instr->value()));
|
| @@ -4355,32 +4340,28 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
|
| void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
|
| DwVfpRegister value = ToDoubleRegister(instr->value());
|
| Register elements = ToRegister(instr->elements());
|
| - Register key = no_reg;
|
| Register scratch = scratch0();
|
| + DwVfpRegister double_scratch = double_scratch0();
|
| bool key_is_constant = instr->key()->IsConstantOperand();
|
| - int constant_key = 0;
|
|
|
| // Calculate the effective address of the slot in the array to store the
|
| // double value.
|
| + int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
|
| if (key_is_constant) {
|
| - constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
|
| + int constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
|
| if (constant_key & 0xF0000000) {
|
| Abort(kArrayIndexConstantValueTooBig);
|
| }
|
| + __ add(scratch, elements,
|
| + Operand((constant_key << element_size_shift) +
|
| + FixedDoubleArray::kHeaderSize - kHeapObjectTag));
|
| } else {
|
| - key = ToRegister(instr->key());
|
| - }
|
| - int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
|
| - int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
|
| - ? (element_size_shift - kSmiTagSize) : element_size_shift;
|
| - Operand operand = key_is_constant
|
| - ? Operand((constant_key << element_size_shift) +
|
| - FixedDoubleArray::kHeaderSize - kHeapObjectTag)
|
| - : Operand(key, LSL, shift_size);
|
| - __ add(scratch, elements, operand);
|
| - if (!key_is_constant) {
|
| - __ add(scratch, scratch,
|
| + int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
|
| + ? (element_size_shift - kSmiTagSize) : element_size_shift;
|
| + __ add(scratch, elements,
|
| Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
|
| + __ add(scratch, scratch,
|
| + Operand(ToRegister(instr->key()), LSL, shift_size));
|
| }
|
|
|
| if (instr->NeedsCanonicalization()) {
|
| @@ -4390,9 +4371,13 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
|
| __ tst(ip, Operand(kVFPDefaultNaNModeControlBit));
|
| __ Assert(ne, kDefaultNaNModeNotSet);
|
| }
|
| - __ VFPCanonicalizeNaN(value);
|
| + __ VFPCanonicalizeNaN(double_scratch, value);
|
| + __ vstr(double_scratch, scratch,
|
| + instr->additional_index() << element_size_shift);
|
| + } else {
|
| + __ vstr(value, scratch,
|
| + instr->additional_index() << element_size_shift);
|
| }
|
| - __ vstr(value, scratch, instr->additional_index() << element_size_shift);
|
| }
|
|
|
|
|
| @@ -4621,17 +4606,11 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
|
|
|
| void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
|
| LOperand* input = instr->value();
|
| - ASSERT(input->IsRegister() || input->IsStackSlot());
|
| LOperand* output = instr->result();
|
| + ASSERT(input->IsRegister());
|
| ASSERT(output->IsDoubleRegister());
|
| SwVfpRegister single_scratch = double_scratch0().low();
|
| - if (input->IsStackSlot()) {
|
| - Register scratch = scratch0();
|
| - __ ldr(scratch, ToMemOperand(input));
|
| - __ vmov(single_scratch, scratch);
|
| - } else {
|
| - __ vmov(single_scratch, ToRegister(input));
|
| - }
|
| + __ vmov(single_scratch, ToRegister(input));
|
| __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch);
|
| }
|
|
|
| @@ -5313,11 +5292,11 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
|
| if (instr->hydrogen()->MustPrefillWithFiller()) {
|
| if (instr->size()->IsConstantOperand()) {
|
| int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
|
| - __ mov(scratch, Operand(size));
|
| + __ mov(scratch, Operand(size - kPointerSize));
|
| } else {
|
| - scratch = ToRegister(instr->size());
|
| + Register size = ToRegister(instr->size());
|
| + __ sub(scratch, size, Operand(kPointerSize));
|
| }
|
| - __ sub(scratch, scratch, Operand(kPointerSize));
|
| __ sub(result, result, Operand(kHeapObjectTag));
|
| Label loop;
|
| __ bind(&loop);
|
| @@ -5462,22 +5441,21 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
| Register scratch = scratch0();
|
| if (type_name->Equals(heap()->number_string())) {
|
| __ JumpIfSmi(input, true_label);
|
| - __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
|
| - __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
| - __ cmp(input, Operand(ip));
|
| + __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
|
| + __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
|
| final_branch_condition = eq;
|
|
|
| } else if (type_name->Equals(heap()->string_string())) {
|
| __ JumpIfSmi(input, false_label);
|
| - __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
|
| + __ CompareObjectType(input, scratch, no_reg, FIRST_NONSTRING_TYPE);
|
| __ b(ge, false_label);
|
| - __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
| - __ tst(ip, Operand(1 << Map::kIsUndetectable));
|
| + __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
| + __ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
| final_branch_condition = eq;
|
|
|
| } else if (type_name->Equals(heap()->symbol_string())) {
|
| __ JumpIfSmi(input, false_label);
|
| - __ CompareObjectType(input, input, scratch, SYMBOL_TYPE);
|
| + __ CompareObjectType(input, scratch, no_reg, SYMBOL_TYPE);
|
| final_branch_condition = eq;
|
|
|
| } else if (type_name->Equals(heap()->boolean_string())) {
|
| @@ -5495,17 +5473,18 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
| __ b(eq, true_label);
|
| __ JumpIfSmi(input, false_label);
|
| // Check for undetectable objects => true.
|
| - __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
|
| - __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
| - __ tst(ip, Operand(1 << Map::kIsUndetectable));
|
| + __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
|
| + __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
| + __ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
| final_branch_condition = ne;
|
|
|
| } else if (type_name->Equals(heap()->function_string())) {
|
| STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
| + Register type_reg = scratch;
|
| __ JumpIfSmi(input, false_label);
|
| - __ CompareObjectType(input, scratch, input, JS_FUNCTION_TYPE);
|
| + __ CompareObjectType(input, scratch, type_reg, JS_FUNCTION_TYPE);
|
| __ b(eq, true_label);
|
| - __ cmp(input, Operand(JS_FUNCTION_PROXY_TYPE));
|
| + __ cmp(type_reg, Operand(JS_FUNCTION_PROXY_TYPE));
|
| final_branch_condition = eq;
|
|
|
| } else if (type_name->Equals(heap()->object_string())) {
|
| @@ -5514,14 +5493,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
| __ CompareRoot(input, Heap::kNullValueRootIndex);
|
| __ b(eq, true_label);
|
| }
|
| - __ CompareObjectType(input, input, scratch,
|
| - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
| - __ b(lt, false_label);
|
| - __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
| - __ b(gt, false_label);
|
| + __ CheckObjectTypeRange(input,
|
| + scratch,
|
| + FIRST_NONCALLABLE_SPEC_OBJECT_TYPE,
|
| + LAST_NONCALLABLE_SPEC_OBJECT_TYPE,
|
| + false_label);
|
| // Check for undetectable objects => false.
|
| - __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
|
| - __ tst(ip, Operand(1 << Map::kIsUndetectable));
|
| + __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
| + __ tst(scratch, Operand(1 << Map::kIsUndetectable));
|
| final_branch_condition = eq;
|
|
|
| } else {
|
|
|