Revision f230a1cf deps/v8/src/ia32/lithium-ia32.cc

View differences:

deps/v8/src/ia32/lithium-ia32.cc
386 386
}
387 387

  
388 388

  
389
int LPlatformChunk::GetNextSpillIndex(bool is_double) {
389
int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
390 390
  // Skip a slot if for a double-width slot.
391
  if (is_double) {
391
  if (kind == DOUBLE_REGISTERS) {
392 392
    spill_slot_count_++;
393 393
    spill_slot_count_ |= 1;
394 394
    num_double_slots_++;
......
397 397
}
398 398

  
399 399

  
400
LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
401
  int index = GetNextSpillIndex(is_double);
402
  if (is_double) {
400
LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
401
  int index = GetNextSpillIndex(kind);
402
  if (kind == DOUBLE_REGISTERS) {
403 403
    return LDoubleStackSlot::Create(index, zone());
404 404
  } else {
405
    ASSERT(kind == GENERAL_REGISTERS);
405 406
    return LStackSlot::Create(index, zone());
406 407
  }
407 408
}
......
479 480

  
480 481
  // Reserve the first spill slot for the state of dynamic alignment.
481 482
  if (info()->IsOptimizing()) {
482
    int alignment_state_index = chunk_->GetNextSpillIndex(false);
483
    int alignment_state_index = chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
483 484
    ASSERT_EQ(alignment_state_index, 0);
484 485
    USE(alignment_state_index);
485 486
  }
......
488 489
  // which will be subsumed into this frame.
489 490
  if (graph()->has_osr()) {
490 491
    for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
491
      chunk_->GetNextSpillIndex(false);
492
      chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
492 493
    }
493 494
  }
494 495

  
......
560 561
}
561 562

  
562 563

  
564
static inline bool CanBeImmediateConstant(HValue* value) {
565
  return value->IsConstant() && HConstant::cast(value)->NotInNewSpace();
566
}
567

  
568

  
563 569
LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
564
  return value->IsConstant()
570
  return CanBeImmediateConstant(value)
565 571
      ? chunk_->DefineConstantOperand(HConstant::cast(value))
566 572
      : Use(value);
567 573
}
568 574

  
569 575

  
570 576
LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
571
  return value->IsConstant()
577
  return CanBeImmediateConstant(value)
572 578
      ? chunk_->DefineConstantOperand(HConstant::cast(value))
573 579
      : UseAtStart(value);
574 580
}
575 581

  
576 582

  
577 583
LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
578
  return value->IsConstant()
584
  return CanBeImmediateConstant(value)
579 585
      ? chunk_->DefineConstantOperand(HConstant::cast(value))
580 586
      : UseRegister(value);
581 587
}
582 588

  
583 589

  
584 590
LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
585
  return value->IsConstant()
591
  return CanBeImmediateConstant(value)
586 592
      ? chunk_->DefineConstantOperand(HConstant::cast(value))
587 593
      : UseRegisterAtStart(value);
588 594
}
......
707 713

  
708 714
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
709 715
  ASSERT(!instr->HasPointerMap());
710
  instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
716
  instr->set_pointer_map(new(zone()) LPointerMap(zone()));
711 717
  return instr;
712 718
}
713 719

  
......
762 768

  
763 769
LInstruction* LChunkBuilder::DoShift(Token::Value op,
764 770
                                     HBitwiseBinaryOperation* instr) {
765
  if (instr->representation().IsTagged()) {
766
    ASSERT(instr->left()->representation().IsSmiOrTagged());
767
    ASSERT(instr->right()->representation().IsSmiOrTagged());
768

  
769
    LOperand* context = UseFixed(instr->context(), esi);
770
    LOperand* left = UseFixed(instr->left(), edx);
771
    LOperand* right = UseFixed(instr->right(), eax);
772
    LArithmeticT* result = new(zone()) LArithmeticT(op, context, left, right);
773
    return MarkAsCall(DefineFixed(result, eax), instr);
774
  }
775

  
776
  ASSERT(instr->representation().IsSmiOrInteger32());
777
  ASSERT(instr->left()->representation().Equals(instr->representation()));
778
  ASSERT(instr->right()->representation().Equals(instr->representation()));
779
  LOperand* left = UseRegisterAtStart(instr->left());
771
  if (instr->representation().IsSmiOrInteger32()) {
772
    ASSERT(instr->left()->representation().Equals(instr->representation()));
773
    ASSERT(instr->right()->representation().Equals(instr->representation()));
774
    LOperand* left = UseRegisterAtStart(instr->left());
780 775

  
781
  HValue* right_value = instr->right();
782
  LOperand* right = NULL;
783
  int constant_value = 0;
784
  bool does_deopt = false;
785
  if (right_value->IsConstant()) {
786
    HConstant* constant = HConstant::cast(right_value);
787
    right = chunk_->DefineConstantOperand(constant);
788
    constant_value = constant->Integer32Value() & 0x1f;
789
    // Left shifts can deoptimize if we shift by > 0 and the result cannot be
790
    // truncated to smi.
791
    if (instr->representation().IsSmi() && constant_value > 0) {
792
      does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
776
    HValue* right_value = instr->right();
777
    LOperand* right = NULL;
778
    int constant_value = 0;
779
    bool does_deopt = false;
780
    if (right_value->IsConstant()) {
781
      HConstant* constant = HConstant::cast(right_value);
782
      right = chunk_->DefineConstantOperand(constant);
783
      constant_value = constant->Integer32Value() & 0x1f;
784
      // Left shifts can deoptimize if we shift by > 0 and the result cannot be
785
      // truncated to smi.
786
      if (instr->representation().IsSmi() && constant_value > 0) {
787
        does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
788
      }
789
    } else {
790
      right = UseFixed(right_value, ecx);
793 791
    }
794
  } else {
795
    right = UseFixed(right_value, ecx);
796
  }
797 792

  
798
  // Shift operations can only deoptimize if we do a logical shift by 0 and
799
  // the result cannot be truncated to int32.
800
  if (op == Token::SHR && constant_value == 0) {
801
    if (FLAG_opt_safe_uint32_operations) {
802
      does_deopt = !instr->CheckFlag(HInstruction::kUint32);
803
    } else {
804
      does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
793
    // Shift operations can only deoptimize if we do a logical shift by 0 and
794
    // the result cannot be truncated to int32.
795
    if (op == Token::SHR && constant_value == 0) {
796
      if (FLAG_opt_safe_uint32_operations) {
797
        does_deopt = !instr->CheckFlag(HInstruction::kUint32);
798
      } else {
799
        does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
800
      }
805 801
    }
806
  }
807 802

  
808
  LInstruction* result =
809
      DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
810
  return does_deopt ? AssignEnvironment(result) : result;
803
    LInstruction* result =
804
        DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
805
    return does_deopt ? AssignEnvironment(result) : result;
806
  } else {
807
    return DoArithmeticT(op, instr);
808
  }
811 809
}
812 810

  
813 811

  
......
816 814
  ASSERT(instr->representation().IsDouble());
817 815
  ASSERT(instr->left()->representation().IsDouble());
818 816
  ASSERT(instr->right()->representation().IsDouble());
819
  ASSERT(op != Token::MOD);
820
  LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
821
  LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
822
  LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
823
  return DefineSameAsFirst(result);
817
  if (op == Token::MOD) {
818
    LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
819
    LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
820
    LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
821
    return MarkAsCall(DefineSameAsFirst(result), instr);
822
  } else {
823
    LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
824
    LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
825
    LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
826
    return DefineSameAsFirst(result);
827
  }
824 828
}
825 829

  
826 830

  
827 831
LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
828
                                           HArithmeticBinaryOperation* instr) {
829
  ASSERT(op == Token::ADD ||
830
         op == Token::DIV ||
831
         op == Token::MOD ||
832
         op == Token::MUL ||
833
         op == Token::SUB);
832
                                           HBinaryOperation* instr) {
834 833
  HValue* left = instr->left();
835 834
  HValue* right = instr->right();
836 835
  ASSERT(left->representation().IsTagged());
......
914 913
void LChunkBuilder::VisitInstruction(HInstruction* current) {
915 914
  HInstruction* old_current = current_instruction_;
916 915
  current_instruction_ = current;
917
  if (current->has_position()) position_ = current->position();
918
  LInstruction* instr = current->CompileToLithium(this);
916

  
917
  LInstruction* instr = NULL;
918
  if (current->CanReplaceWithDummyUses()) {
919
    HValue* first_operand = current->OperandCount() == 0
920
        ? graph()->GetConstant1()
921
        : current->OperandAt(0);
922
    instr = DefineAsRegister(new(zone()) LDummyUse(UseAny(first_operand)));
923
    for (int i = 1; i < current->OperandCount(); ++i) {
924
      LInstruction* dummy =
925
          new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
926
      dummy->set_hydrogen_value(current);
927
      chunk_->AddInstruction(dummy, current_block_);
928
    }
929
  } else {
930
    instr = current->CompileToLithium(this);
931
  }
932

  
933
  argument_count_ += current->argument_delta();
934
  ASSERT(argument_count_ >= 0);
919 935

  
920 936
  if (instr != NULL) {
937
    // Associate the hydrogen instruction first, since we may need it for
938
    // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
939
    instr->set_hydrogen_value(current);
940

  
921 941
#if DEBUG
922 942
    // Make sure that the lithium instruction has either no fixed register
923 943
    // constraints in temps or the result OR no uses that are only used at
......
947 967
    }
948 968
#endif
949 969

  
950
    instr->set_position(position_);
951 970
    if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
952 971
      instr = AssignPointerMap(instr);
953 972
    }
......
964 983
      clobber->set_hydrogen_value(current);
965 984
      chunk_->AddInstruction(clobber, current_block_);
966 985
    }
967
    instr->set_hydrogen_value(current);
968 986
    chunk_->AddInstruction(instr, current_block_);
969 987
  }
970 988
  current_instruction_ = old_current;
......
1061 1079

  
1062 1080

  
1063 1081
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
1064
  HValue* value = instr->value();
1065
  if (value->EmitAtUses()) {
1066
    ASSERT(value->IsConstant());
1067
    ASSERT(!value->representation().IsDouble());
1068
    HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
1069
        ? instr->FirstSuccessor()
1070
        : instr->SecondSuccessor();
1071
    return new(zone()) LGoto(successor);
1072
  }
1082
  LInstruction* goto_instr = CheckElideControlInstruction(instr);
1083
  if (goto_instr != NULL) return goto_instr;
1073 1084

  
1074 1085
  ToBooleanStub::Types expected = instr->expected_input_types();
1075 1086

  
1076 1087
  // Tagged values that are not known smis or booleans require a
1077 1088
  // deoptimization environment. If the instruction is generic no
1078 1089
  // environment is needed since all cases are handled.
1090
  HValue* value = instr->value();
1079 1091
  Representation rep = value->representation();
1080 1092
  HType type = value->type();
1081 1093
  if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) {
......
1141 1153
}
1142 1154

  
1143 1155

  
1144
LInstruction* LChunkBuilder::DoInstanceSize(HInstanceSize* instr) {
1145
  LOperand* object = UseRegisterAtStart(instr->object());
1146
  return DefineAsRegister(new(zone()) LInstanceSize(object));
1147
}
1148

  
1149

  
1150 1156
LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1151 1157
  LOperand* receiver = UseRegister(instr->receiver());
1152 1158
  LOperand* function = UseRegisterAtStart(instr->function());
......
1171 1177

  
1172 1178

  
1173 1179
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1174
  ++argument_count_;
1175 1180
  LOperand* argument = UseAny(instr->argument());
1176 1181
  return new(zone()) LPushArgument(argument);
1177 1182
}
......
1238 1243

  
1239 1244
LInstruction* LChunkBuilder::DoCallConstantFunction(
1240 1245
    HCallConstantFunction* instr) {
1241
  argument_count_ -= instr->argument_count();
1242 1246
  return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, eax), instr);
1243 1247
}
1244 1248

  
......
1246 1250
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1247 1251
  LOperand* context = UseFixed(instr->context(), esi);
1248 1252
  LOperand* function = UseFixed(instr->function(), edi);
1249
  argument_count_ -= instr->argument_count();
1250 1253
  LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
1251 1254
  return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1252 1255
}
......
1356 1359
  ASSERT(instr->key()->representation().IsTagged());
1357 1360
  LOperand* context = UseFixed(instr->context(), esi);
1358 1361
  LOperand* key = UseFixed(instr->key(), ecx);
1359
  argument_count_ -= instr->argument_count();
1360 1362
  LCallKeyed* result = new(zone()) LCallKeyed(context, key);
1361 1363
  return MarkAsCall(DefineFixed(result, eax), instr);
1362 1364
}
......
1364 1366

  
1365 1367
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1366 1368
  LOperand* context = UseFixed(instr->context(), esi);
1367
  argument_count_ -= instr->argument_count();
1368 1369
  LCallNamed* result = new(zone()) LCallNamed(context);
1369 1370
  return MarkAsCall(DefineFixed(result, eax), instr);
1370 1371
}
......
1372 1373

  
1373 1374
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1374 1375
  LOperand* context = UseFixed(instr->context(), esi);
1375
  argument_count_ -= instr->argument_count();
1376 1376
  LCallGlobal* result = new(zone()) LCallGlobal(context);
1377 1377
  return MarkAsCall(DefineFixed(result, eax), instr);
1378 1378
}
1379 1379

  
1380 1380

  
1381 1381
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1382
  argument_count_ -= instr->argument_count();
1383 1382
  return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, eax), instr);
1384 1383
}
1385 1384

  
......
1387 1386
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1388 1387
  LOperand* context = UseFixed(instr->context(), esi);
1389 1388
  LOperand* constructor = UseFixed(instr->constructor(), edi);
1390
  argument_count_ -= instr->argument_count();
1391 1389
  LCallNew* result = new(zone()) LCallNew(context, constructor);
1392 1390
  return MarkAsCall(DefineFixed(result, eax), instr);
1393 1391
}
......
1396 1394
LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1397 1395
  LOperand* context = UseFixed(instr->context(), esi);
1398 1396
  LOperand* constructor = UseFixed(instr->constructor(), edi);
1399
  argument_count_ -= instr->argument_count();
1400 1397
  LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
1401 1398
  return MarkAsCall(DefineFixed(result, eax), instr);
1402 1399
}
......
1405 1402
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1406 1403
  LOperand* context = UseFixed(instr->context(), esi);
1407 1404
  LOperand* function = UseFixed(instr->function(), edi);
1408
  argument_count_ -= instr->argument_count();
1409 1405
  LCallFunction* result = new(zone()) LCallFunction(context, function);
1410 1406
  return MarkAsCall(DefineFixed(result, eax), instr);
1411 1407
}
1412 1408

  
1413 1409

  
1414 1410
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1415
  argument_count_ -= instr->argument_count();
1416 1411
  LOperand* context = UseFixed(instr->context(), esi);
1417 1412
  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr);
1418 1413
}
......
1442 1437
  if (instr->representation().IsSmiOrInteger32()) {
1443 1438
    ASSERT(instr->left()->representation().Equals(instr->representation()));
1444 1439
    ASSERT(instr->right()->representation().Equals(instr->representation()));
1440
    ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
1445 1441

  
1446 1442
    LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1447 1443
    LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1448 1444
    return DefineSameAsFirst(new(zone()) LBitI(left, right));
1449 1445
  } else {
1450
    ASSERT(instr->representation().IsSmiOrTagged());
1451
    ASSERT(instr->left()->representation().IsSmiOrTagged());
1452
    ASSERT(instr->right()->representation().IsSmiOrTagged());
1453

  
1454
    LOperand* context = UseFixed(instr->context(), esi);
1455
    LOperand* left = UseFixed(instr->left(), edx);
1456
    LOperand* right = UseFixed(instr->right(), eax);
1457
    LArithmeticT* result =
1458
        new(zone()) LArithmeticT(instr->op(), context, left, right);
1459
    return MarkAsCall(DefineFixed(result, eax), instr);
1446
    return DoArithmeticT(instr->op(), instr);
1460 1447
  }
1461 1448
}
1462 1449

  
1463 1450

  
1464 1451
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1465
  if (instr->representation().IsDouble()) {
1466
    return DoArithmeticD(Token::DIV, instr);
1467
  } else if (instr->representation().IsSmiOrInteger32()) {
1452
  if (instr->representation().IsSmiOrInteger32()) {
1468 1453
    ASSERT(instr->left()->representation().Equals(instr->representation()));
1469 1454
    ASSERT(instr->right()->representation().Equals(instr->representation()));
1470 1455
    if (instr->HasPowerOf2Divisor()) {
......
1481 1466
    LOperand* divisor = UseRegister(instr->right());
1482 1467
    LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
1483 1468
    return AssignEnvironment(DefineFixed(result, eax));
1469
  } else if (instr->representation().IsDouble()) {
1470
    return DoArithmeticD(Token::DIV, instr);
1484 1471
  } else {
1485
    ASSERT(instr->representation().IsTagged());
1486 1472
    return DoArithmeticT(Token::DIV, instr);
1487 1473
  }
1488 1474
}
......
1584 1570
          ? AssignEnvironment(result)
1585 1571
          : result;
1586 1572
    }
1587
  } else if (instr->representation().IsSmiOrTagged()) {
1588
    return DoArithmeticT(Token::MOD, instr);
1573
  } else if (instr->representation().IsDouble()) {
1574
    return DoArithmeticD(Token::MOD, instr);
1589 1575
  } else {
1590
    ASSERT(instr->representation().IsDouble());
1591
    // We call a C function for double modulo. It can't trigger a GC. We need
1592
    // to use fixed result register for the call.
1593
    // TODO(fschneider): Allow any register as input registers.
1594
    LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD,
1595
                                                 UseFixedDouble(left, xmm2),
1596
                                                 UseFixedDouble(right, xmm1));
1597
    return MarkAsCall(DefineFixedDouble(mod, xmm1), instr);
1576
    return DoArithmeticT(Token::MOD, instr);
1598 1577
  }
1599 1578
}
1600 1579

  
......
1618 1597
  } else if (instr->representation().IsDouble()) {
1619 1598
    return DoArithmeticD(Token::MUL, instr);
1620 1599
  } else {
1621
    ASSERT(instr->representation().IsTagged());
1622 1600
    return DoArithmeticT(Token::MUL, instr);
1623 1601
  }
1624 1602
}
......
1639 1617
  } else if (instr->representation().IsDouble()) {
1640 1618
    return DoArithmeticD(Token::SUB, instr);
1641 1619
  } else {
1642
    ASSERT(instr->representation().IsSmiOrTagged());
1643 1620
    return DoArithmeticT(Token::SUB, instr);
1644 1621
  }
1645 1622
}
......
1671 1648
  } else if (instr->representation().IsDouble()) {
1672 1649
    return DoArithmeticD(Token::ADD, instr);
1673 1650
  } else {
1674
    ASSERT(instr->representation().IsSmiOrTagged());
1675 1651
    return DoArithmeticT(Token::ADD, instr);
1676 1652
  }
1677 1653
}
......
1752 1728
    ASSERT(instr->right()->representation().IsDouble());
1753 1729
    LOperand* left;
1754 1730
    LOperand* right;
1755
    if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1756
      left = UseRegisterOrConstantAtStart(instr->left());
1757
      right = UseRegisterOrConstantAtStart(instr->right());
1731
    if (CanBeImmediateConstant(instr->left()) &&
1732
        CanBeImmediateConstant(instr->right())) {
1733
      // The code generator requires either both inputs to be constant
1734
      // operands, or neither.
1735
      left = UseConstant(instr->left());
1736
      right = UseConstant(instr->right());
1758 1737
    } else {
1759 1738
      left = UseRegisterAtStart(instr->left());
1760 1739
      right = UseRegisterAtStart(instr->right());
......
1766 1745

  
1767 1746
LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1768 1747
    HCompareObjectEqAndBranch* instr) {
1748
  LInstruction* goto_instr = CheckElideControlInstruction(instr);
1749
  if (goto_instr != NULL) return goto_instr;
1769 1750
  LOperand* left = UseRegisterAtStart(instr->left());
1770 1751
  LOperand* right = UseOrConstantAtStart(instr->right());
1771 1752
  return new(zone()) LCmpObjectEqAndBranch(left, right);
......
1774 1755

  
1775 1756
LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1776 1757
    HCompareHoleAndBranch* instr) {
1777
  LOperand* object = UseRegisterAtStart(instr->object());
1778
  return new(zone()) LCmpHoleAndBranch(object);
1758
  LOperand* value = UseRegisterAtStart(instr->value());
1759
  return new(zone()) LCmpHoleAndBranch(value);
1779 1760
}
1780 1761

  
1781 1762

  
......
1909 1890
}
1910 1891

  
1911 1892

  
1893
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1894
  // The control instruction marking the end of a block that completed
1895
  // abruptly (e.g., threw an exception).  There is nothing specific to do.
1896
  return NULL;
1897
}
1898

  
1899

  
1912 1900
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1913 1901
  LOperand* context = UseFixed(instr->context(), esi);
1914 1902
  LOperand* value = UseFixed(instr->value(), eax);
......
1944 1932
  // building a stack frame.
1945 1933
  if (from.IsTagged()) {
1946 1934
    if (to.IsDouble()) {
1947
      info()->MarkAsDeferredCalling();
1948 1935
      LOperand* value = UseRegister(instr->value());
1949 1936
      // Temp register only necessary for minus zero check.
1950 1937
      LOperand* temp = TempRegister();
......
2015 2002
    } else if (to.IsSmi()) {
2016 2003
      HValue* val = instr->value();
2017 2004
      LOperand* value = UseRegister(val);
2018
      LInstruction* result =
2019
          DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
2005
      LInstruction* result = val->CheckFlag(HInstruction::kUint32)
2006
           ? DefineSameAsFirst(new(zone()) LUint32ToSmi(value))
2007
           : DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
2020 2008
      if (val->HasRange() && val->range()->IsInSmiRange()) {
2021 2009
        return result;
2022 2010
      }
......
2050 2038
}
2051 2039

  
2052 2040

  
2053
LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) {
2054
  return new(zone())
2055
    LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value()));
2056
}
2057

  
2058

  
2059 2041
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
2060 2042
  LOperand* value = UseRegisterAtStart(instr->value());
2061 2043
  LOperand* temp = TempRegister();
......
2234 2216
}
2235 2217

  
2236 2218

  
2219
LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2220
  return DefineAsRegister(new(zone()) LLoadRoot);
2221
}
2222

  
2223

  
2237 2224
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
2238 2225
    HLoadExternalArrayPointer* instr) {
2239 2226
  LOperand* input = UseRegisterAtStart(instr->value());
......
2435 2422
      !(FLAG_track_double_fields && instr->field_representation().IsDouble());
2436 2423

  
2437 2424
  LOperand* val;
2438
  if (needs_write_barrier) {
2425
  if (instr->field_representation().IsByte()) {
2426
    // mov_b requires a byte register (i.e. any of eax, ebx, ecx, edx).
2427
    // Just force the value to be in eax and we're safe here.
2428
    val = UseFixed(instr->value(), eax);
2429
  } else if (needs_write_barrier) {
2439 2430
    val = UseTempRegister(instr->value());
2440 2431
  } else if (can_be_constant) {
2441 2432
    val = UseRegisterOrConstant(instr->value());
......
2582 2573

  
2583 2574
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2584 2575
  LOperand* context = UseFixed(instr->context(), esi);
2585
  argument_count_ -= instr->argument_count();
2586 2576
  LCallStub* result = new(zone()) LCallStub(context);
2587 2577
  return MarkAsCall(DefineFixed(result, eax), instr);
2588 2578
}
......
2711 2701
  if (env->entry()->arguments_pushed()) {
2712 2702
    int argument_count = env->arguments_environment()->parameter_count();
2713 2703
    pop = new(zone()) LDrop(argument_count);
2714
    argument_count_ -= argument_count;
2704
    ASSERT(instr->argument_delta() == -argument_count);
2715 2705
  }
2716 2706

  
2717 2707
  HEnvironment* outer = current_block_->last_environment()->

Also available in: Unified diff