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

View differences:

deps/v8/src/arm/lithium-arm.cc
412 412
}
413 413

  
414 414

  
415
int LPlatformChunk::GetNextSpillIndex(bool is_double) {
415
int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
416 416
  // Skip a slot if for a double-width slot.
417
  if (is_double) spill_slot_count_++;
417
  if (kind == DOUBLE_REGISTERS) spill_slot_count_++;
418 418
  return spill_slot_count_++;
419 419
}
420 420

  
421 421

  
422
LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double)  {
423
  int index = GetNextSpillIndex(is_double);
424
  if (is_double) {
422
LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind)  {
423
  int index = GetNextSpillIndex(kind);
424
  if (kind == DOUBLE_REGISTERS) {
425 425
    return LDoubleStackSlot::Create(index, zone());
426 426
  } else {
427
    ASSERT(kind == GENERAL_REGISTERS);
427 428
    return LStackSlot::Create(index, zone());
428 429
  }
429 430
}
......
439 440
  // which will be subsumed into this frame.
440 441
  if (graph()->has_osr()) {
441 442
    for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
442
      chunk_->GetNextSpillIndex(false);
443
      chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
443 444
    }
444 445
  }
445 446

  
......
655 656

  
656 657
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
657 658
  ASSERT(!instr->HasPointerMap());
658
  instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
659
  instr->set_pointer_map(new(zone()) LPointerMap(zone()));
659 660
  return instr;
660 661
}
661 662

  
......
710 711

  
711 712
LInstruction* LChunkBuilder::DoShift(Token::Value op,
712 713
                                     HBitwiseBinaryOperation* instr) {
713
  if (instr->representation().IsTagged()) {
714
    ASSERT(instr->left()->representation().IsTagged());
715
    ASSERT(instr->right()->representation().IsTagged());
716

  
717
    LOperand* left = UseFixed(instr->left(), r1);
718
    LOperand* right = UseFixed(instr->right(), r0);
719
    LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
720
    return MarkAsCall(DefineFixed(result, r0), instr);
721
  }
722

  
723
  ASSERT(instr->representation().IsSmiOrInteger32());
724
  ASSERT(instr->left()->representation().Equals(instr->representation()));
725
  ASSERT(instr->right()->representation().Equals(instr->representation()));
726
  LOperand* left = UseRegisterAtStart(instr->left());
714
  if (instr->representation().IsSmiOrInteger32()) {
715
    ASSERT(instr->left()->representation().Equals(instr->representation()));
716
    ASSERT(instr->right()->representation().Equals(instr->representation()));
717
    LOperand* left = UseRegisterAtStart(instr->left());
727 718

  
728
  HValue* right_value = instr->right();
729
  LOperand* right = NULL;
730
  int constant_value = 0;
731
  bool does_deopt = false;
732
  if (right_value->IsConstant()) {
733
    HConstant* constant = HConstant::cast(right_value);
734
    right = chunk_->DefineConstantOperand(constant);
735
    constant_value = constant->Integer32Value() & 0x1f;
736
    // Left shifts can deoptimize if we shift by > 0 and the result cannot be
737
    // truncated to smi.
738
    if (instr->representation().IsSmi() && constant_value > 0) {
739
      does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
719
    HValue* right_value = instr->right();
720
    LOperand* right = NULL;
721
    int constant_value = 0;
722
    bool does_deopt = false;
723
    if (right_value->IsConstant()) {
724
      HConstant* constant = HConstant::cast(right_value);
725
      right = chunk_->DefineConstantOperand(constant);
726
      constant_value = constant->Integer32Value() & 0x1f;
727
      // Left shifts can deoptimize if we shift by > 0 and the result cannot be
728
      // truncated to smi.
729
      if (instr->representation().IsSmi() && constant_value > 0) {
730
        does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
731
      }
732
    } else {
733
      right = UseRegisterAtStart(right_value);
740 734
    }
741
  } else {
742
    right = UseRegisterAtStart(right_value);
743
  }
744 735

  
745
  // Shift operations can only deoptimize if we do a logical shift
746
  // by 0 and the result cannot be truncated to int32.
747
  if (op == Token::SHR && constant_value == 0) {
748
    if (FLAG_opt_safe_uint32_operations) {
749
      does_deopt = !instr->CheckFlag(HInstruction::kUint32);
750
    } else {
751
      does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
736
    // Shift operations can only deoptimize if we do a logical shift
737
    // by 0 and the result cannot be truncated to int32.
738
    if (op == Token::SHR && constant_value == 0) {
739
      if (FLAG_opt_safe_uint32_operations) {
740
        does_deopt = !instr->CheckFlag(HInstruction::kUint32);
741
      } else {
742
        does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
743
      }
752 744
    }
753
  }
754 745

  
755
  LInstruction* result =
756
      DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
757
  return does_deopt ? AssignEnvironment(result) : result;
746
    LInstruction* result =
747
        DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
748
    return does_deopt ? AssignEnvironment(result) : result;
749
  } else {
750
    return DoArithmeticT(op, instr);
751
  }
758 752
}
759 753

  
760 754

  
......
763 757
  ASSERT(instr->representation().IsDouble());
764 758
  ASSERT(instr->left()->representation().IsDouble());
765 759
  ASSERT(instr->right()->representation().IsDouble());
766
  ASSERT(op != Token::MOD);
767
  LOperand* left = UseRegisterAtStart(instr->left());
768
  LOperand* right = UseRegisterAtStart(instr->right());
769
  LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
770
  return DefineAsRegister(result);
760
  if (op == Token::MOD) {
761
    LOperand* left = UseFixedDouble(instr->left(), d1);
762
    LOperand* right = UseFixedDouble(instr->right(), d2);
763
    LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
764
    // We call a C function for double modulo. It can't trigger a GC. We need
765
    // to use fixed result register for the call.
766
    // TODO(fschneider): Allow any register as input registers.
767
    return MarkAsCall(DefineFixedDouble(result, d1), instr);
768
  } else {
769
    LOperand* left = UseRegisterAtStart(instr->left());
770
    LOperand* right = UseRegisterAtStart(instr->right());
771
    LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
772
    return DefineAsRegister(result);
773
  }
771 774
}
772 775

  
773 776

  
774 777
LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
775
                                           HArithmeticBinaryOperation* instr) {
776
  ASSERT(op == Token::ADD ||
777
         op == Token::DIV ||
778
         op == Token::MOD ||
779
         op == Token::MUL ||
780
         op == Token::SUB);
778
                                           HBinaryOperation* instr) {
781 779
  HValue* left = instr->left();
782 780
  HValue* right = instr->right();
783 781
  ASSERT(left->representation().IsTagged());
784 782
  ASSERT(right->representation().IsTagged());
783
  LOperand* context = UseFixed(instr->context(), cp);
785 784
  LOperand* left_operand = UseFixed(left, r1);
786 785
  LOperand* right_operand = UseFixed(right, r0);
787 786
  LArithmeticT* result =
788
      new(zone()) LArithmeticT(op, left_operand, right_operand);
787
      new(zone()) LArithmeticT(op, context, left_operand, right_operand);
789 788
  return MarkAsCall(DefineFixed(result, r0), instr);
790 789
}
791 790

  
......
861 860
  HInstruction* old_current = current_instruction_;
862 861
  current_instruction_ = current;
863 862
  if (current->has_position()) position_ = current->position();
864
  LInstruction* instr = current->CompileToLithium(this);
863

  
864
  LInstruction* instr = NULL;
865
  if (current->CanReplaceWithDummyUses()) {
866
    HValue* first_operand = current->OperandCount() == 0
867
        ? graph()->GetConstant1()
868
        : current->OperandAt(0);
869
    instr = DefineAsRegister(new(zone()) LDummyUse(UseAny(first_operand)));
870
    for (int i = 1; i < current->OperandCount(); ++i) {
871
      LInstruction* dummy =
872
          new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
873
      dummy->set_hydrogen_value(current);
874
      chunk_->AddInstruction(dummy, current_block_);
875
    }
876
  } else {
877
    instr = current->CompileToLithium(this);
878
  }
879

  
880
  argument_count_ += current->argument_delta();
881
  ASSERT(argument_count_ >= 0);
865 882

  
866 883
  if (instr != NULL) {
884
    // Associate the hydrogen instruction first, since we may need it for
885
    // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
886
    instr->set_hydrogen_value(current);
887

  
867 888
#if DEBUG
868 889
    // Make sure that the lithium instruction has either no fixed register
869 890
    // constraints in temps or the result OR no uses that are only used at
......
893 914
    }
894 915
#endif
895 916

  
896
    instr->set_position(position_);
897 917
    if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
898 918
      instr = AssignPointerMap(instr);
899 919
    }
900 920
    if (FLAG_stress_environments && !instr->HasEnvironment()) {
901 921
      instr = AssignEnvironment(instr);
902 922
    }
903
    instr->set_hydrogen_value(current);
904 923
    chunk_->AddInstruction(instr, current_block_);
905 924
  }
906 925
  current_instruction_ = old_current;
......
992 1011

  
993 1012

  
994 1013
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
995
  return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
1014
  return new(zone()) LGoto(instr->FirstSuccessor());
996 1015
}
997 1016

  
998 1017

  
999 1018
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
1000
  HValue* value = instr->value();
1001
  if (value->EmitAtUses()) {
1002
    HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
1003
        ? instr->FirstSuccessor()
1004
        : instr->SecondSuccessor();
1005
    return new(zone()) LGoto(successor->block_id());
1006
  }
1019
  LInstruction* goto_instr = CheckElideControlInstruction(instr);
1020
  if (goto_instr != NULL) return goto_instr;
1007 1021

  
1022
  HValue* value = instr->value();
1008 1023
  LBranch* result = new(zone()) LBranch(UseRegister(value));
1009 1024
  // Tagged values that are not known smis or booleans require a
1010 1025
  // deoptimization environment. If the instruction is generic no
......
1047 1062

  
1048 1063

  
1049 1064
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1065
  LOperand* context = UseFixed(instr->context(), cp);
1050 1066
  LInstanceOf* result =
1051
      new(zone()) LInstanceOf(UseFixed(instr->left(), r0),
1052
                      UseFixed(instr->right(), r1));
1067
      new(zone()) LInstanceOf(context, UseFixed(instr->left(), r0),
1068
                              UseFixed(instr->right(), r1));
1053 1069
  return MarkAsCall(DefineFixed(result, r0), instr);
1054 1070
}
1055 1071

  
......
1057 1073
LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1058 1074
    HInstanceOfKnownGlobal* instr) {
1059 1075
  LInstanceOfKnownGlobal* result =
1060
      new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), r0),
1061
                                         FixedTemp(r4));
1076
      new(zone()) LInstanceOfKnownGlobal(
1077
          UseFixed(instr->context(), cp),
1078
          UseFixed(instr->left(), r0),
1079
          FixedTemp(r4));
1062 1080
  return MarkAsCall(DefineFixed(result, r0), instr);
1063 1081
}
1064 1082

  
1065 1083

  
1066
LInstruction* LChunkBuilder::DoInstanceSize(HInstanceSize* instr) {
1067
  LOperand* object = UseRegisterAtStart(instr->object());
1068
  return DefineAsRegister(new(zone()) LInstanceSize(object));
1069
}
1070

  
1071

  
1072 1084
LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1073 1085
  LOperand* receiver = UseRegisterAtStart(instr->receiver());
1074 1086
  LOperand* function = UseRegisterAtStart(instr->function());
......
1091 1103

  
1092 1104

  
1093 1105
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1094
  ++argument_count_;
1095 1106
  LOperand* argument = Use(instr->argument());
1096 1107
  return new(zone()) LPushArgument(argument);
1097 1108
}
......
1122 1133

  
1123 1134

  
1124 1135
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1125
  // If there is a non-return use, the context must be allocated in a register.
1126
  for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
1127
    if (!it.value()->IsReturn()) {
1128
      return DefineAsRegister(new(zone()) LContext);
1129
    }
1136
  if (instr->HasNoUses()) return NULL;
1137

  
1138
  if (info()->IsStub()) {
1139
    return DefineFixed(new(zone()) LContext, cp);
1130 1140
  }
1131 1141

  
1132
  return NULL;
1142
  return DefineAsRegister(new(zone()) LContext);
1133 1143
}
1134 1144

  
1135 1145

  
......
1140 1150

  
1141 1151

  
1142 1152
LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1143
  return MarkAsCall(new(zone()) LDeclareGlobals, instr);
1153
  LOperand* context = UseFixed(instr->context(), cp);
1154
  return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
1144 1155
}
1145 1156

  
1146 1157

  
......
1158 1169

  
1159 1170
LInstruction* LChunkBuilder::DoCallConstantFunction(
1160 1171
    HCallConstantFunction* instr) {
1161
  argument_count_ -= instr->argument_count();
1162 1172
  return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, r0), instr);
1163 1173
}
1164 1174

  
1165 1175

  
1166 1176
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1177
  LOperand* context = UseFixed(instr->context(), cp);
1167 1178
  LOperand* function = UseFixed(instr->function(), r1);
1168
  argument_count_ -= instr->argument_count();
1169
  LInvokeFunction* result = new(zone()) LInvokeFunction(function);
1179
  LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
1170 1180
  return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1171 1181
}
1172 1182

  
......
1206 1216

  
1207 1217

  
1208 1218
LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1219
  Representation r = instr->value()->representation();
1220
  LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32())
1221
      ? NULL
1222
      : UseFixed(instr->context(), cp);
1209 1223
  LOperand* input = UseRegister(instr->value());
1210
  LMathAbs* result = new(zone()) LMathAbs(input);
1224
  LMathAbs* result = new(zone()) LMathAbs(context, input);
1211 1225
  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1212 1226
}
1213 1227

  
......
1243 1257
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1244 1258
  ASSERT(instr->representation().IsDouble());
1245 1259
  ASSERT(instr->value()->representation().IsDouble());
1246
  LOperand* input = UseTempRegister(instr->value());
1260
  LOperand* input = UseRegister(instr->value());
1247 1261
  LOperand* temp1 = TempRegister();
1248 1262
  LOperand* temp2 = TempRegister();
1249 1263
  LOperand* double_temp = FixedTemp(d3);  // Chosen by fair dice roll.
......
1269 1283

  
1270 1284
LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1271 1285
  ASSERT(instr->key()->representation().IsTagged());
1272
  argument_count_ -= instr->argument_count();
1286
  LOperand* context = UseFixed(instr->context(), cp);
1273 1287
  LOperand* key = UseFixed(instr->key(), r2);
1274
  return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), r0), instr);
1288
  return MarkAsCall(
1289
        DefineFixed(new(zone()) LCallKeyed(context, key), r0), instr);
1275 1290
}
1276 1291

  
1277 1292

  
1278 1293
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1279
  argument_count_ -= instr->argument_count();
1280
  return MarkAsCall(DefineFixed(new(zone()) LCallNamed, r0), instr);
1294
  LOperand* context = UseFixed(instr->context(), cp);
1295
  return MarkAsCall(DefineFixed(new(zone()) LCallNamed(context), r0), instr);
1281 1296
}
1282 1297

  
1283 1298

  
1284 1299
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1285
  argument_count_ -= instr->argument_count();
1286
  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, r0), instr);
1300
  LOperand* context = UseFixed(instr->context(), cp);
1301
  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal(context), r0), instr);
1287 1302
}
1288 1303

  
1289 1304

  
1290 1305
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1291
  argument_count_ -= instr->argument_count();
1292 1306
  return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, r0), instr);
1293 1307
}
1294 1308

  
1295 1309

  
1296 1310
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1311
  LOperand* context = UseFixed(instr->context(), cp);
1297 1312
  LOperand* constructor = UseFixed(instr->constructor(), r1);
1298
  argument_count_ -= instr->argument_count();
1299
  LCallNew* result = new(zone()) LCallNew(constructor);
1313
  LCallNew* result = new(zone()) LCallNew(context, constructor);
1300 1314
  return MarkAsCall(DefineFixed(result, r0), instr);
1301 1315
}
1302 1316

  
1303 1317

  
1304 1318
LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1319
  LOperand* context = UseFixed(instr->context(), cp);
1305 1320
  LOperand* constructor = UseFixed(instr->constructor(), r1);
1306
  argument_count_ -= instr->argument_count();
1307
  LCallNewArray* result = new(zone()) LCallNewArray(constructor);
1321
  LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
1308 1322
  return MarkAsCall(DefineFixed(result, r0), instr);
1309 1323
}
1310 1324

  
1311 1325

  
1312 1326
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1327
  LOperand* context = UseFixed(instr->context(), cp);
1313 1328
  LOperand* function = UseFixed(instr->function(), r1);
1314
  argument_count_ -= instr->argument_count();
1315
  return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), r0),
1316
                    instr);
1329
  return MarkAsCall(
1330
      DefineFixed(new(zone()) LCallFunction(context, function), r0), instr);
1317 1331
}
1318 1332

  
1319 1333

  
1320 1334
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1321
  argument_count_ -= instr->argument_count();
1322
  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, r0), instr);
1335
  LOperand* context = UseFixed(instr->context(), cp);
1336
  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), r0), instr);
1323 1337
}
1324 1338

  
1325 1339

  
......
1347 1361
  if (instr->representation().IsSmiOrInteger32()) {
1348 1362
    ASSERT(instr->left()->representation().Equals(instr->representation()));
1349 1363
    ASSERT(instr->right()->representation().Equals(instr->representation()));
1364
    ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
1350 1365

  
1351 1366
    LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1352 1367
    LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1353 1368
    return DefineAsRegister(new(zone()) LBitI(left, right));
1354 1369
  } else {
1355
    ASSERT(instr->representation().IsTagged());
1356
    ASSERT(instr->left()->representation().IsTagged());
1357
    ASSERT(instr->right()->representation().IsTagged());
1358

  
1359
    LOperand* left = UseFixed(instr->left(), r1);
1360
    LOperand* right = UseFixed(instr->right(), r0);
1361
    LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
1362
    return MarkAsCall(DefineFixed(result, r0), instr);
1370
    return DoArithmeticT(instr->op(), instr);
1363 1371
  }
1364 1372
}
1365 1373

  
1366 1374

  
1367 1375
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1368
  if (instr->representation().IsDouble()) {
1369
    return DoArithmeticD(Token::DIV, instr);
1370
  } else if (instr->representation().IsSmiOrInteger32()) {
1376
  if (instr->representation().IsSmiOrInteger32()) {
1371 1377
    ASSERT(instr->left()->representation().Equals(instr->representation()));
1372 1378
    ASSERT(instr->right()->representation().Equals(instr->representation()));
1373 1379
    if (instr->HasPowerOf2Divisor()) {
1374 1380
      ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1375 1381
      LOperand* value = UseRegisterAtStart(instr->left());
1376
      LDivI* div =
1377
          new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL);
1378
      return AssignEnvironment(DefineSameAsFirst(div));
1382
      LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL);
1383
      return AssignEnvironment(DefineAsRegister(div));
1379 1384
    }
1380 1385
    LOperand* dividend = UseRegister(instr->left());
1381 1386
    LOperand* divisor = UseRegister(instr->right());
1382 1387
    LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4);
1383 1388
    LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
1384 1389
    return AssignEnvironment(DefineAsRegister(div));
1390
  } else if (instr->representation().IsDouble()) {
1391
    return DoArithmeticD(Token::DIV, instr);
1385 1392
  } else {
1386 1393
    return DoArithmeticT(Token::DIV, instr);
1387 1394
  }
......
1502 1509
          ? AssignEnvironment(result)
1503 1510
          : result;
1504 1511
    }
1505
  } else if (instr->representation().IsTagged()) {
1506
    return DoArithmeticT(Token::MOD, instr);
1512
  } else if (instr->representation().IsDouble()) {
1513
    return DoArithmeticD(Token::MOD, instr);
1507 1514
  } else {
1508
    ASSERT(instr->representation().IsDouble());
1509
    // We call a C function for double modulo. It can't trigger a GC. We need
1510
    // to use fixed result register for the call.
1511
    // TODO(fschneider): Allow any register as input registers.
1512
    LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD,
1513
                                                 UseFixedDouble(left, d1),
1514
                                                 UseFixedDouble(right, d2));
1515
    return MarkAsCall(DefineFixedDouble(mod, d1), instr);
1515
    return DoArithmeticT(Token::MOD, instr);
1516 1516
  }
1517 1517
}
1518 1518

  
......
1679 1679

  
1680 1680
    return DoArithmeticD(Token::ADD, instr);
1681 1681
  } else {
1682
    ASSERT(instr->representation().IsTagged());
1683 1682
    return DoArithmeticT(Token::ADD, instr);
1684 1683
  }
1685 1684
}
......
1737 1736
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1738 1737
  ASSERT(instr->left()->representation().IsTagged());
1739 1738
  ASSERT(instr->right()->representation().IsTagged());
1739
  LOperand* context = UseFixed(instr->context(), cp);
1740 1740
  LOperand* left = UseFixed(instr->left(), r1);
1741 1741
  LOperand* right = UseFixed(instr->right(), r0);
1742
  LCmpT* result = new(zone()) LCmpT(left, right);
1742
  LCmpT* result = new(zone()) LCmpT(context, left, right);
1743 1743
  return MarkAsCall(DefineFixed(result, r0), instr);
1744 1744
}
1745 1745

  
......
1766 1766

  
1767 1767
LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1768 1768
    HCompareObjectEqAndBranch* instr) {
1769
  LInstruction* goto_instr = CheckElideControlInstruction(instr);
1770
  if (goto_instr != NULL) return goto_instr;
1769 1771
  LOperand* left = UseRegisterAtStart(instr->left());
1770 1772
  LOperand* right = UseRegisterAtStart(instr->right());
1771 1773
  return new(zone()) LCmpObjectEqAndBranch(left, right);
......
1774 1776

  
1775 1777
LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1776 1778
    HCompareHoleAndBranch* instr) {
1777
  LOperand* object = UseRegisterAtStart(instr->object());
1778
  return new(zone()) LCmpHoleAndBranch(object);
1779
  LOperand* value = UseRegisterAtStart(instr->value());
1780
  return new(zone()) LCmpHoleAndBranch(value);
1779 1781
}
1780 1782

  
1781 1783

  
......
1813 1815
    HStringCompareAndBranch* instr) {
1814 1816
  ASSERT(instr->left()->representation().IsTagged());
1815 1817
  ASSERT(instr->right()->representation().IsTagged());
1818
  LOperand* context = UseFixed(instr->context(), cp);
1816 1819
  LOperand* left = UseFixed(instr->left(), r1);
1817 1820
  LOperand* right = UseFixed(instr->right(), r0);
1818 1821
  LStringCompareAndBranch* result =
1819
      new(zone()) LStringCompareAndBranch(left, right);
1822
      new(zone()) LStringCompareAndBranch(context, left, right);
1820 1823
  return MarkAsCall(result, instr);
1821 1824
}
1822 1825

  
......
1883 1886

  
1884 1887
LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1885 1888
  LOperand* string = UseRegister(instr->string());
1886
  LOperand* index = UseRegister(instr->index());
1887
  LOperand* value = UseTempRegister(instr->value());
1888
  LSeqStringSetChar* result =
1889
      new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
1890
  return DefineAsRegister(result);
1889
  LOperand* index = UseRegisterOrConstant(instr->index());
1890
  LOperand* value = UseRegister(instr->value());
1891
  return new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
1891 1892
}
1892 1893

  
1893 1894

  
......
1905 1906
}
1906 1907

  
1907 1908

  
1909
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1910
  // The control instruction marking the end of a block that completed
1911
  // abruptly (e.g., threw an exception).  There is nothing specific to do.
1912
  return NULL;
1913
}
1914

  
1915

  
1908 1916
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1917
  LOperand* context = UseFixed(instr->context(), cp);
1909 1918
  LOperand* value = UseFixed(instr->value(), r0);
1910
  return MarkAsCall(new(zone()) LThrow(value), instr);
1919
  return MarkAsCall(new(zone()) LThrow(context, value), instr);
1911 1920
}
1912 1921

  
1913 1922

  
......
1936 1945
  }
1937 1946
  if (from.IsTagged()) {
1938 1947
    if (to.IsDouble()) {
1939
      info()->MarkAsDeferredCalling();
1940 1948
      LOperand* value = UseRegister(instr->value());
1941 1949
      LNumberUntagD* res = new(zone()) LNumberUntagD(value);
1942 1950
      return AssignEnvironment(DefineAsRegister(res));
......
2006 2014
    } else if (to.IsSmi()) {
2007 2015
      HValue* val = instr->value();
2008 2016
      LOperand* value = UseRegister(val);
2009
      LInstruction* result =
2010
          DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
2017
      LInstruction* result = val->CheckFlag(HInstruction::kUint32)
2018
          ? DefineSameAsFirst(new(zone()) LUint32ToSmi(value))
2019
          : DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
2011 2020
      if (val->HasRange() && val->range()->IsInSmiRange()) {
2012 2021
        return result;
2013 2022
      }
......
2040 2049
}
2041 2050

  
2042 2051

  
2043
LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) {
2044
  return new(zone())
2045
    LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value()));
2046
}
2047

  
2048

  
2049 2052
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
2050 2053
  LOperand* value = UseRegisterAtStart(instr->value());
2051 2054
  LInstruction* result = new(zone()) LCheckInstanceType(value);
......
2093 2096

  
2094 2097

  
2095 2098
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
2099
  LOperand* context = info()->IsStub()
2100
      ? UseFixed(instr->context(), cp)
2101
      : NULL;
2096 2102
  LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
2097
  return new(zone()) LReturn(UseFixed(instr->value(), r0),
2103
  return new(zone()) LReturn(UseFixed(instr->value(), r0), context,
2098 2104
                             parameter_count);
2099 2105
}
2100 2106

  
......
2127 2133

  
2128 2134

  
2129 2135
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2136
  LOperand* context = UseFixed(instr->context(), cp);
2130 2137
  LOperand* global_object = UseFixed(instr->global_object(), r0);
2131
  LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
2138
  LLoadGlobalGeneric* result =
2139
      new(zone()) LLoadGlobalGeneric(context, global_object);
2132 2140
  return MarkAsCall(DefineFixed(result, r0), instr);
2133 2141
}
2134 2142

  
......
2144 2152

  
2145 2153

  
2146 2154
LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
2155
  LOperand* context = UseFixed(instr->context(), cp);
2147 2156
  LOperand* global_object = UseFixed(instr->global_object(), r1);
2148 2157
  LOperand* value = UseFixed(instr->value(), r0);
2149 2158
  LStoreGlobalGeneric* result =
2150
      new(zone()) LStoreGlobalGeneric(global_object, value);
2159
      new(zone()) LStoreGlobalGeneric(context, global_object, value);
2151 2160
  return MarkAsCall(result, instr);
2152 2161
}
2153 2162

  
......
2182 2191

  
2183 2192

  
2184 2193
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2194
  LOperand* context = UseFixed(instr->context(), cp);
2185 2195
  LOperand* object = UseFixed(instr->object(), r0);
2186
  LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), r0);
2196
  LInstruction* result =
2197
      DefineFixed(new(zone()) LLoadNamedGeneric(context, object), r0);
2187 2198
  return MarkAsCall(result, instr);
2188 2199
}
2189 2200

  
......
2195 2206
}
2196 2207

  
2197 2208

  
2209
LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2210
  return DefineAsRegister(new(zone()) LLoadRoot);
2211
}
2212

  
2213

  
2198 2214
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
2199 2215
    HLoadExternalArrayPointer* instr) {
2200 2216
  LOperand* input = UseRegisterAtStart(instr->value());
......
2211 2227
  if (!instr->is_external()) {
2212 2228
    LOperand* obj = NULL;
2213 2229
    if (instr->representation().IsDouble()) {
2214
      obj = UseTempRegister(instr->elements());
2230
      obj = UseRegister(instr->elements());
2215 2231
    } else {
2216 2232
      ASSERT(instr->representation().IsSmiOrTagged());
2217 2233
      obj = UseRegisterAtStart(instr->elements());
......
2239 2255

  
2240 2256

  
2241 2257
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2258
  LOperand* context = UseFixed(instr->context(), cp);
2242 2259
  LOperand* object = UseFixed(instr->object(), r1);
2243 2260
  LOperand* key = UseFixed(instr->key(), r0);
2244 2261

  
2245 2262
  LInstruction* result =
2246
      DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r0);
2263
      DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), r0);
2247 2264
  return MarkAsCall(result, instr);
2248 2265
}
2249 2266

  
2250 2267

  
2251 2268
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2252
  ElementsKind elements_kind = instr->elements_kind();
2253

  
2254 2269
  if (!instr->is_external()) {
2255 2270
    ASSERT(instr->elements()->representation().IsTagged());
2256 2271
    bool needs_write_barrier = instr->NeedsWriteBarrier();
......
2260 2275

  
2261 2276
    if (instr->value()->representation().IsDouble()) {
2262 2277
      object = UseRegisterAtStart(instr->elements());
2263
      val = UseTempRegister(instr->value());
2278
      val = UseRegister(instr->value());
2264 2279
      key = UseRegisterOrConstantAtStart(instr->key());
2265 2280
    } else {
2266 2281
      ASSERT(instr->value()->representation().IsSmiOrTagged());
2267
      object = UseTempRegister(instr->elements());
2268
      val = needs_write_barrier ? UseTempRegister(instr->value())
2269
          : UseRegisterAtStart(instr->value());
2270
      key = needs_write_barrier ? UseTempRegister(instr->key())
2271
          : UseRegisterOrConstantAtStart(instr->key());
2282
      if (needs_write_barrier) {
2283
        object = UseTempRegister(instr->elements());
2284
        val = UseTempRegister(instr->value());
2285
        key = UseTempRegister(instr->key());
2286
      } else {
2287
        object = UseRegisterAtStart(instr->elements());
2288
        val = UseRegisterAtStart(instr->value());
2289
        key = UseRegisterOrConstantAtStart(instr->key());
2290
      }
2272 2291
    }
2273 2292

  
2274 2293
    return new(zone()) LStoreKeyed(object, key, val);
......
2276 2295

  
2277 2296
  ASSERT(
2278 2297
      (instr->value()->representation().IsInteger32() &&
2279
       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2280
       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2298
       (instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) &&
2299
       (instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) ||
2281 2300
      (instr->value()->representation().IsDouble() &&
2282
       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2283
        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2301
       ((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) ||
2302
        (instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS))));
2284 2303
  ASSERT(instr->elements()->representation().IsExternal());
2285
  bool val_is_temp_register =
2286
      elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
2287
      elements_kind == EXTERNAL_FLOAT_ELEMENTS;
2288
  LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
2289
      : UseRegister(instr->value());
2304
  LOperand* val = UseRegister(instr->value());
2290 2305
  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2291 2306
  LOperand* external_pointer = UseRegister(instr->elements());
2292 2307
  return new(zone()) LStoreKeyed(external_pointer, key, val);
......
2294 2309

  
2295 2310

  
2296 2311
LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2312
  LOperand* context = UseFixed(instr->context(), cp);
2297 2313
  LOperand* obj = UseFixed(instr->object(), r2);
2298 2314
  LOperand* key = UseFixed(instr->key(), r1);
2299 2315
  LOperand* val = UseFixed(instr->value(), r0);
......
2302 2318
  ASSERT(instr->key()->representation().IsTagged());
2303 2319
  ASSERT(instr->value()->representation().IsTagged());
2304 2320

  
2305
  return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
2321
  return MarkAsCall(
2322
      new(zone()) LStoreKeyedGeneric(context, obj, key, val), instr);
2306 2323
}
2307 2324

  
2308 2325

  
......
2312 2329
  if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
2313 2330
    LOperand* new_map_reg = TempRegister();
2314 2331
    LTransitionElementsKind* result =
2315
        new(zone()) LTransitionElementsKind(object, new_map_reg);
2332
        new(zone()) LTransitionElementsKind(object, NULL, new_map_reg);
2316 2333
    return result;
2317 2334
  } else {
2335
    LOperand* context = UseFixed(instr->context(), cp);
2318 2336
    LTransitionElementsKind* result =
2319
        new(zone()) LTransitionElementsKind(object, NULL);
2337
        new(zone()) LTransitionElementsKind(object, context, NULL);
2320 2338
    return AssignPointerMap(result);
2321 2339
  }
2322 2340
}
......
2375 2393

  
2376 2394

  
2377 2395
LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2396
  LOperand* context = UseFixed(instr->context(), cp);
2378 2397
  LOperand* obj = UseFixed(instr->object(), r1);
2379 2398
  LOperand* val = UseFixed(instr->value(), r0);
2380 2399

  
2381
  LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
2400
  LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val);
2382 2401
  return MarkAsCall(result, instr);
2383 2402
}
2384 2403

  
2385 2404

  
2386 2405
LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2406
  LOperand* context = UseFixed(instr->context(), cp);
2387 2407
  LOperand* left = UseRegisterAtStart(instr->left());
2388 2408
  LOperand* right = UseRegisterAtStart(instr->right());
2389
  return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), r0),
2390
                    instr);
2409
  return MarkAsCall(
2410
      DefineFixed(new(zone()) LStringAdd(context, left, right), r0),
2411
      instr);
2391 2412
}
2392 2413

  
2393 2414

  
2394 2415
LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2395 2416
  LOperand* string = UseTempRegister(instr->string());
2396 2417
  LOperand* index = UseTempRegister(instr->index());
2397
  LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
2418
  LOperand* context = UseAny(instr->context());
2419
  LStringCharCodeAt* result =
2420
      new(zone()) LStringCharCodeAt(context, string, index);
2398 2421
  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2399 2422
}
2400 2423

  
2401 2424

  
2402 2425
LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2403 2426
  LOperand* char_code = UseRegister(instr->value());
2404
  LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
2427
  LOperand* context = UseAny(instr->context());
2428
  LStringCharFromCode* result =
2429
      new(zone()) LStringCharFromCode(context, char_code);
2405 2430
  return AssignPointerMap(DefineAsRegister(result));
2406 2431
}
2407 2432

  
2408 2433

  
2409 2434
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2410 2435
  info()->MarkAsDeferredCalling();
2436
  LOperand* context = UseAny(instr->context());
2411 2437
  LOperand* size = instr->size()->IsConstant()
2412 2438
      ? UseConstant(instr->size())
2413 2439
      : UseTempRegister(instr->size());
2414 2440
  LOperand* temp1 = TempRegister();
2415 2441
  LOperand* temp2 = TempRegister();
2416
  LAllocate* result = new(zone()) LAllocate(size, temp1, temp2);
2442
  LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
2417 2443
  return AssignPointerMap(DefineAsRegister(result));
2418 2444
}
2419 2445

  
2420 2446

  
2421 2447
LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2422
  return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, r0), instr);
2448
  LOperand* context = UseFixed(instr->context(), cp);
2449
  return MarkAsCall(
2450
      DefineFixed(new(zone()) LRegExpLiteral(context), r0), instr);
2423 2451
}
2424 2452

  
2425 2453

  
2426 2454
LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2427
  return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, r0), instr);
2455
  LOperand* context = UseFixed(instr->context(), cp);
2456
  return MarkAsCall(
2457
      DefineFixed(new(zone()) LFunctionLiteral(context), r0), instr);
2428 2458
}
2429 2459

  
2430 2460

  
......
2471 2501

  
2472 2502

  
2473 2503
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2474
  argument_count_ -= instr->argument_count();
2475
  return MarkAsCall(DefineFixed(new(zone()) LCallStub, r0), instr);
2504
  LOperand* context = UseFixed(instr->context(), cp);
2505
  return MarkAsCall(DefineFixed(new(zone()) LCallStub(context), r0), instr);
2476 2506
}
2477 2507

  
2478 2508

  
......
2517 2547

  
2518 2548

  
2519 2549
LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2520
  LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), r0));
2550
  LOperand* context = UseFixed(instr->context(), cp);
2551
  LTypeof* result = new(zone()) LTypeof(context, UseFixed(instr->value(), r0));
2521 2552
  return MarkAsCall(DefineFixed(result, r0), instr);
2522 2553
}
2523 2554

  
......
2556 2587

  
2557 2588
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2558 2589
  if (instr->is_function_entry()) {
2559
    return MarkAsCall(new(zone()) LStackCheck, instr);
2590
    LOperand* context = UseFixed(instr->context(), cp);
2591
    return MarkAsCall(new(zone()) LStackCheck(context), instr);
2560 2592
  } else {
2561 2593
    ASSERT(instr->is_backwards_branch());
2562
    return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
2594
    LOperand* context = UseAny(instr->context());
2595
    return AssignEnvironment(
2596
        AssignPointerMap(new(zone()) LStackCheck(context)));
2563 2597
  }
2564 2598
}
2565 2599

  
......
2592 2626
  if (env->entry()->arguments_pushed()) {
2593 2627
    int argument_count = env->arguments_environment()->parameter_count();
2594 2628
    pop = new(zone()) LDrop(argument_count);
2595
    argument_count_ -= argument_count;
2629
    ASSERT(instr->argument_delta() == -argument_count);
2596 2630
  }
2597 2631

  
2598 2632
  HEnvironment* outer = current_block_->last_environment()->
......
2604 2638

  
2605 2639

  
2606 2640
LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2641
  LOperand* context = UseFixed(instr->context(), cp);
2607 2642
  LOperand* object = UseFixed(instr->enumerable(), r0);
2608
  LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
2643
  LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
2609 2644
  return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
2610 2645
}
2611 2646

  

Also available in: Unified diff