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

View differences:

deps/v8/src/mips/lithium-mips.cc
417 417
}
418 418

  
419 419

  
420
int LPlatformChunk::GetNextSpillIndex(bool is_double) {
420
int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
421 421
  // Skip a slot if for a double-width slot.
422
  if (is_double) spill_slot_count_++;
422
  if (kind == DOUBLE_REGISTERS) spill_slot_count_++;
423 423
  return spill_slot_count_++;
424 424
}
425 425

  
426 426

  
427
LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double)  {
428
  int index = GetNextSpillIndex(is_double);
429
  if (is_double) {
427
LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind)  {
428
  int index = GetNextSpillIndex(kind);
429
  if (kind == DOUBLE_REGISTERS) {
430 430
    return LDoubleStackSlot::Create(index, zone());
431 431
  } else {
432
    ASSERT(kind == GENERAL_REGISTERS);
432 433
    return LStackSlot::Create(index, zone());
433 434
  }
434 435
}
......
444 445
  // which will be subsumed into this frame.
445 446
  if (graph()->has_osr()) {
446 447
    for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
447
      chunk_->GetNextSpillIndex(false);
448
      chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
448 449
    }
449 450
  }
450 451

  
......
660 661

  
661 662
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
662 663
  ASSERT(!instr->HasPointerMap());
663
  instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
664
  instr->set_pointer_map(new(zone()) LPointerMap(zone()));
664 665
  return instr;
665 666
}
666 667

  
......
715 716

  
716 717
LInstruction* LChunkBuilder::DoShift(Token::Value op,
717 718
                                     HBitwiseBinaryOperation* instr) {
718
  if (instr->representation().IsTagged()) {
719
    ASSERT(instr->left()->representation().IsTagged());
720
    ASSERT(instr->right()->representation().IsTagged());
721

  
722
    LOperand* left = UseFixed(instr->left(), a1);
723
    LOperand* right = UseFixed(instr->right(), a0);
724
    LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
725
    return MarkAsCall(DefineFixed(result, v0), instr);
726
  }
727

  
728
  ASSERT(instr->representation().IsSmiOrInteger32());
729
  ASSERT(instr->left()->representation().Equals(instr->representation()));
730
  ASSERT(instr->right()->representation().Equals(instr->representation()));
731
  LOperand* left = UseRegisterAtStart(instr->left());
719
  if (instr->representation().IsSmiOrInteger32()) {
720
    ASSERT(instr->left()->representation().Equals(instr->representation()));
721
    ASSERT(instr->right()->representation().Equals(instr->representation()));
722
    LOperand* left = UseRegisterAtStart(instr->left());
732 723

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

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

  
760
  LInstruction* result =
761
      DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
762
  return does_deopt ? AssignEnvironment(result) : result;
751
    LInstruction* result =
752
        DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
753
    return does_deopt ? AssignEnvironment(result) : result;
754
  } else {
755
    return DoArithmeticT(op, instr);
756
  }
763 757
}
764 758

  
765 759

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

  
778 781

  
779 782
LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
780
                                           HArithmeticBinaryOperation* instr) {
781
  ASSERT(op == Token::ADD ||
782
         op == Token::DIV ||
783
         op == Token::MOD ||
784
         op == Token::MUL ||
785
         op == Token::SUB);
783
                                           HBinaryOperation* instr) {
786 784
  HValue* left = instr->left();
787 785
  HValue* right = instr->right();
788 786
  ASSERT(left->representation().IsTagged());
789 787
  ASSERT(right->representation().IsTagged());
788
  LOperand* context = UseFixed(instr->context(), cp);
790 789
  LOperand* left_operand = UseFixed(left, a1);
791 790
  LOperand* right_operand = UseFixed(right, a0);
792 791
  LArithmeticT* result =
793
      new(zone()) LArithmeticT(op, left_operand, right_operand);
792
      new(zone()) LArithmeticT(op, context, left_operand, right_operand);
794 793
  return MarkAsCall(DefineFixed(result, v0), instr);
795 794
}
796 795

  
......
866 865
  HInstruction* old_current = current_instruction_;
867 866
  current_instruction_ = current;
868 867
  if (current->has_position()) position_ = current->position();
869
  LInstruction* instr = current->CompileToLithium(this);
868

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

  
885
  argument_count_ += current->argument_delta();
886
  ASSERT(argument_count_ >= 0);
870 887

  
871 888
  if (instr != NULL) {
889
    // Associate the hydrogen instruction first, since we may need it for
890
    // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
891
    instr->set_hydrogen_value(current);
892

  
872 893
#if DEBUG
873 894
    // Make sure that the lithium instruction has either no fixed register
874 895
    // constraints in temps or the result OR no uses that are only used at
......
898 919
    }
899 920
#endif
900 921

  
901
    instr->set_position(position_);
902 922
    if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
903 923
      instr = AssignPointerMap(instr);
904 924
    }
905 925
    if (FLAG_stress_environments && !instr->HasEnvironment()) {
906 926
      instr = AssignEnvironment(instr);
907 927
    }
908
    instr->set_hydrogen_value(current);
909 928
    chunk_->AddInstruction(instr, current_block_);
910 929
  }
911 930
  current_instruction_ = old_current;
......
997 1016

  
998 1017

  
999 1018
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1000
  return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
1019
  return new(zone()) LGoto(instr->FirstSuccessor());
1001 1020
}
1002 1021

  
1003 1022

  
1004 1023
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
1005
  HValue* value = instr->value();
1006
  if (value->EmitAtUses()) {
1007
    HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
1008
        ? instr->FirstSuccessor()
1009
        : instr->SecondSuccessor();
1010
    return new(zone()) LGoto(successor->block_id());
1011
  }
1024
  LInstruction* goto_instr = CheckElideControlInstruction(instr);
1025
  if (goto_instr != NULL) return goto_instr;
1012 1026

  
1027
  HValue* value = instr->value();
1013 1028
  LBranch* result = new(zone()) LBranch(UseRegister(value));
1014 1029
  // Tagged values that are not known smis or booleans require a
1015 1030
  // 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(), a0),
1067
      new(zone()) LInstanceOf(context, UseFixed(instr->left(), a0),
1052 1068
                              UseFixed(instr->right(), a1));
1053 1069
  return MarkAsCall(DefineFixed(result, v0), instr);
1054 1070
}
......
1057 1073
LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1058 1074
    HInstanceOfKnownGlobal* instr) {
1059 1075
  LInstanceOfKnownGlobal* result =
1060
      new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), a0),
1061
                                         FixedTemp(t0));
1076
      new(zone()) LInstanceOfKnownGlobal(
1077
          UseFixed(instr->context(), cp),
1078
          UseFixed(instr->left(), a0),
1079
          FixedTemp(t0));
1062 1080
  return MarkAsCall(DefineFixed(result, v0), 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, v0), 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(), a1);
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, v0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1171 1181
}
1172 1182

  
......
1221 1231
LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1222 1232
  ASSERT(instr->representation().IsDouble());
1223 1233
  ASSERT(instr->value()->representation().IsDouble());
1224
  LOperand* input = UseTempRegister(instr->value());
1234
  LOperand* input = UseRegister(instr->value());
1225 1235
  LOperand* temp1 = TempRegister();
1226 1236
  LOperand* temp2 = TempRegister();
1227 1237
  LOperand* double_temp = FixedTemp(f6);  // Chosen by fair dice roll.
......
1240 1250

  
1241 1251

  
1242 1252
LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1253
  Representation r = instr->value()->representation();
1254
  LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32())
1255
      ? NULL
1256
      : UseFixed(instr->context(), cp);
1243 1257
  LOperand* input = UseRegister(instr->value());
1244
  LMathAbs* result = new(zone()) LMathAbs(input);
1258
  LMathAbs* result = new(zone()) LMathAbs(context, input);
1245 1259
  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1246 1260
}
1247 1261

  
......
1271 1285

  
1272 1286
LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1273 1287
  ASSERT(instr->key()->representation().IsTagged());
1274
  argument_count_ -= instr->argument_count();
1288
  LOperand* context = UseFixed(instr->context(), cp);
1275 1289
  LOperand* key = UseFixed(instr->key(), a2);
1276
  return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), v0), instr);
1290
  return MarkAsCall(
1291
        DefineFixed(new(zone()) LCallKeyed(context, key), v0), instr);
1277 1292
}
1278 1293

  
1279 1294

  
1280 1295
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1281
  argument_count_ -= instr->argument_count();
1282
  return MarkAsCall(DefineFixed(new(zone()) LCallNamed, v0), instr);
1296
  LOperand* context = UseFixed(instr->context(), cp);
1297
  return MarkAsCall(DefineFixed(new(zone()) LCallNamed(context), v0), instr);
1283 1298
}
1284 1299

  
1285 1300

  
1286 1301
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1287
  argument_count_ -= instr->argument_count();
1288
  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, v0), instr);
1302
  LOperand* context = UseFixed(instr->context(), cp);
1303
  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal(context), v0), instr);
1289 1304
}
1290 1305

  
1291 1306

  
1292 1307
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1293
  argument_count_ -= instr->argument_count();
1294 1308
  return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, v0), instr);
1295 1309
}
1296 1310

  
1297 1311

  
1298 1312
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1313
  LOperand* context = UseFixed(instr->context(), cp);
1299 1314
  LOperand* constructor = UseFixed(instr->constructor(), a1);
1300
  argument_count_ -= instr->argument_count();
1301
  LCallNew* result = new(zone()) LCallNew(constructor);
1315
  LCallNew* result = new(zone()) LCallNew(context, constructor);
1302 1316
  return MarkAsCall(DefineFixed(result, v0), instr);
1303 1317
}
1304 1318

  
1305 1319

  
1306 1320
LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1321
  LOperand* context = UseFixed(instr->context(), cp);
1307 1322
  LOperand* constructor = UseFixed(instr->constructor(), a1);
1308
  argument_count_ -= instr->argument_count();
1309
  LCallNewArray* result = new(zone()) LCallNewArray(constructor);
1323
  LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
1310 1324
  return MarkAsCall(DefineFixed(result, v0), instr);
1311 1325
}
1312 1326

  
1313 1327

  
1314 1328
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1329
  LOperand* context = UseFixed(instr->context(), cp);
1315 1330
  LOperand* function = UseFixed(instr->function(), a1);
1316
  argument_count_ -= instr->argument_count();
1317
  return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), v0),
1318
                    instr);
1331
  return MarkAsCall(
1332
      DefineFixed(new(zone()) LCallFunction(context, function), v0), instr);
1319 1333
}
1320 1334

  
1321 1335

  
1322 1336
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1323
  argument_count_ -= instr->argument_count();
1324
  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, v0), instr);
1337
  LOperand* context = UseFixed(instr->context(), cp);
1338
  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), v0), instr);
1325 1339
}
1326 1340

  
1327 1341

  
......
1349 1363
  if (instr->representation().IsSmiOrInteger32()) {
1350 1364
    ASSERT(instr->left()->representation().Equals(instr->representation()));
1351 1365
    ASSERT(instr->right()->representation().Equals(instr->representation()));
1366
    ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
1352 1367

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

  
1361
    LOperand* left = UseFixed(instr->left(), a1);
1362
    LOperand* right = UseFixed(instr->right(), a0);
1363
    LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
1364
    return MarkAsCall(DefineFixed(result, v0), instr);
1372
    return DoArithmeticT(instr->op(), instr);
1365 1373
  }
1366 1374
}
1367 1375

  
1368 1376

  
1369 1377
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1370
  if (instr->representation().IsDouble()) {
1371
    return DoArithmeticD(Token::DIV, instr);
1372
  } else if (instr->representation().IsSmiOrInteger32()) {
1378
  if (instr->representation().IsSmiOrInteger32()) {
1373 1379
    ASSERT(instr->left()->representation().Equals(instr->representation()));
1374 1380
    ASSERT(instr->right()->representation().Equals(instr->representation()));
1375 1381
    LOperand* dividend = UseRegister(instr->left());
1376 1382
    LOperand* divisor = UseRegister(instr->right());
1377 1383
    LDivI* div = new(zone()) LDivI(dividend, divisor);
1378 1384
    return AssignEnvironment(DefineAsRegister(div));
1385
  } else if (instr->representation().IsDouble()) {
1386
    return DoArithmeticD(Token::DIV, instr);
1379 1387
  } else {
1380 1388
    return DoArithmeticT(Token::DIV, instr);
1381 1389
  }
......
1466 1474
          ? AssignEnvironment(result)
1467 1475
          : result;
1468 1476
    }
1469
  } else if (instr->representation().IsTagged()) {
1470
    return DoArithmeticT(Token::MOD, instr);
1477
  } else if (instr->representation().IsDouble()) {
1478
    return DoArithmeticD(Token::MOD, instr);
1471 1479
  } else {
1472
    ASSERT(instr->representation().IsDouble());
1473
    // We call a C function for double modulo. It can't trigger a GC. We need
1474
    // to use fixed result register for the call.
1475
    // TODO(fschneider): Allow any register as input registers.
1476
    LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD,
1477
                                                 UseFixedDouble(left, f2),
1478
                                                 UseFixedDouble(right, f4));
1479
    return MarkAsCall(DefineFixedDouble(mod, f2), instr);
1480
    return DoArithmeticT(Token::MOD, instr);
1480 1481
  }
1481 1482
}
1482 1483

  
......
1485 1486
  if (instr->representation().IsSmiOrInteger32()) {
1486 1487
    ASSERT(instr->left()->representation().Equals(instr->representation()));
1487 1488
    ASSERT(instr->right()->representation().Equals(instr->representation()));
1488
    LOperand* left;
1489
    LOperand* right = UseOrConstant(instr->BetterRightOperand());
1490
    LOperand* temp = NULL;
1491
    if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1492
        (instr->CheckFlag(HValue::kCanOverflow) ||
1493
        !right->IsConstantOperand())) {
1494
      left = UseRegister(instr->BetterLeftOperand());
1495
      temp = TempRegister();
1489
    HValue* left = instr->BetterLeftOperand();
1490
    HValue* right = instr->BetterRightOperand();
1491
    LOperand* left_op;
1492
    LOperand* right_op;
1493
    bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1494
    bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
1495

  
1496
    if (right->IsConstant()) {
1497
      HConstant* constant = HConstant::cast(right);
1498
      int32_t constant_value = constant->Integer32Value();
1499
      // Constants -1, 0 and 1 can be optimized if the result can overflow.
1500
      // For other constants, it can be optimized only without overflow.
1501
      if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) {
1502
        left_op = UseRegisterAtStart(left);
1503
        right_op = UseConstant(right);
1504
      } else {
1505
        if (bailout_on_minus_zero) {
1506
          left_op = UseRegister(left);
1507
        } else {
1508
          left_op = UseRegisterAtStart(left);
1509
        }
1510
        right_op = UseRegister(right);
1511
      }
1496 1512
    } else {
1497
      left = UseRegisterAtStart(instr->BetterLeftOperand());
1513
      if (bailout_on_minus_zero) {
1514
        left_op = UseRegister(left);
1515
      } else {
1516
        left_op = UseRegisterAtStart(left);
1517
      }
1518
      right_op = UseRegister(right);
1498 1519
    }
1499
    LMulI* mul = new(zone()) LMulI(left, right, temp);
1500
    if (instr->CheckFlag(HValue::kCanOverflow) ||
1501
        instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1520
    LMulI* mul = new(zone()) LMulI(left_op, right_op);
1521
    if (can_overflow || bailout_on_minus_zero) {
1502 1522
      AssignEnvironment(mul);
1503 1523
    }
1504 1524
    return DefineAsRegister(mul);
......
1579 1599
    }
1580 1600
    return DoArithmeticD(Token::ADD, instr);
1581 1601
  } else {
1582
    ASSERT(instr->representation().IsTagged());
1583 1602
    return DoArithmeticT(Token::ADD, instr);
1584 1603
  }
1585 1604
}
......
1637 1656
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1638 1657
  ASSERT(instr->left()->representation().IsTagged());
1639 1658
  ASSERT(instr->right()->representation().IsTagged());
1659
  LOperand* context = UseFixed(instr->context(), cp);
1640 1660
  LOperand* left = UseFixed(instr->left(), a1);
1641 1661
  LOperand* right = UseFixed(instr->right(), a0);
1642
  LCmpT* result = new(zone()) LCmpT(left, right);
1662
  LCmpT* result = new(zone()) LCmpT(context, left, right);
1643 1663
  return MarkAsCall(DefineFixed(result, v0), instr);
1644 1664
}
1645 1665

  
......
1666 1686

  
1667 1687
LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1668 1688
    HCompareObjectEqAndBranch* instr) {
1689
  LInstruction* goto_instr = CheckElideControlInstruction(instr);
1690
  if (goto_instr != NULL) return goto_instr;
1669 1691
  LOperand* left = UseRegisterAtStart(instr->left());
1670 1692
  LOperand* right = UseRegisterAtStart(instr->right());
1671 1693
  return new(zone()) LCmpObjectEqAndBranch(left, right);
......
1674 1696

  
1675 1697
LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1676 1698
    HCompareHoleAndBranch* instr) {
1677
  LOperand* object = UseRegisterAtStart(instr->object());
1678
  return new(zone()) LCmpHoleAndBranch(object);
1699
  LOperand* value = UseRegisterAtStart(instr->value());
1700
  return new(zone()) LCmpHoleAndBranch(value);
1679 1701
}
1680 1702

  
1681 1703

  
......
1713 1735
    HStringCompareAndBranch* instr) {
1714 1736
  ASSERT(instr->left()->representation().IsTagged());
1715 1737
  ASSERT(instr->right()->representation().IsTagged());
1738
  LOperand* context = UseFixed(instr->context(), cp);
1716 1739
  LOperand* left = UseFixed(instr->left(), a1);
1717 1740
  LOperand* right = UseFixed(instr->right(), a0);
1718 1741
  LStringCompareAndBranch* result =
1719
      new(zone()) LStringCompareAndBranch(left, right);
1742
      new(zone()) LStringCompareAndBranch(context, left, right);
1720 1743
  return MarkAsCall(result, instr);
1721 1744
}
1722 1745

  
......
1783 1806

  
1784 1807
LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1785 1808
  LOperand* string = UseRegister(instr->string());
1786
  LOperand* index = UseRegister(instr->index());
1787
  LOperand* value = UseTempRegister(instr->value());
1788
  LSeqStringSetChar* result =
1789
      new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
1790
  return DefineAsRegister(result);
1809
  LOperand* index = UseRegisterOrConstant(instr->index());
1810
  LOperand* value = UseRegister(instr->value());
1811
  return new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
1791 1812
}
1792 1813

  
1793 1814

  
......
1805 1826
}
1806 1827

  
1807 1828

  
1829
LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1830
  // The control instruction marking the end of a block that completed
1831
  // abruptly (e.g., threw an exception).  There is nothing specific to do.
1832
  return NULL;
1833
}
1834

  
1835

  
1808 1836
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1837
  LOperand* context = UseFixed(instr->context(), cp);
1809 1838
  LOperand* value = UseFixed(instr->value(), a0);
1810
  return MarkAsCall(new(zone()) LThrow(value), instr);
1839
  return MarkAsCall(new(zone()) LThrow(context, value), instr);
1811 1840
}
1812 1841

  
1813 1842

  
......
1836 1865
  }
1837 1866
  if (from.IsTagged()) {
1838 1867
    if (to.IsDouble()) {
1839
      info()->MarkAsDeferredCalling();
1840 1868
      LOperand* value = UseRegister(instr->value());
1841 1869
      LNumberUntagD* res = new(zone()) LNumberUntagD(value);
1842 1870
      return AssignEnvironment(DefineAsRegister(res));
......
1940 1968
}
1941 1969

  
1942 1970

  
1943
LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) {
1944
  return new(zone())
1945
    LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value()));
1946
}
1947

  
1948

  
1949 1971
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1950 1972
  LOperand* value = UseRegisterAtStart(instr->value());
1951 1973
  LInstruction* result = new(zone()) LCheckInstanceType(value);
......
1994 2016

  
1995 2017

  
1996 2018
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
2019
  LOperand* context = info()->IsStub()
2020
      ? UseFixed(instr->context(), cp)
2021
      : NULL;
1997 2022
  LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1998
  return new(zone()) LReturn(UseFixed(instr->value(), v0),
2023
  return new(zone()) LReturn(UseFixed(instr->value(), v0), context,
1999 2024
                             parameter_count);
2000 2025
}
2001 2026

  
......
2028 2053

  
2029 2054

  
2030 2055
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2056
  LOperand* context = UseFixed(instr->context(), cp);
2031 2057
  LOperand* global_object = UseFixed(instr->global_object(), a0);
2032
  LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
2058
  LLoadGlobalGeneric* result =
2059
      new(zone()) LLoadGlobalGeneric(context, global_object);
2033 2060
  return MarkAsCall(DefineFixed(result, v0), instr);
2034 2061
}
2035 2062

  
......
2045 2072

  
2046 2073

  
2047 2074
LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
2075
  LOperand* context = UseFixed(instr->context(), cp);
2048 2076
  LOperand* global_object = UseFixed(instr->global_object(), a1);
2049 2077
  LOperand* value = UseFixed(instr->value(), a0);
2050 2078
  LStoreGlobalGeneric* result =
2051
      new(zone()) LStoreGlobalGeneric(global_object, value);
2079
      new(zone()) LStoreGlobalGeneric(context, global_object, value);
2052 2080
  return MarkAsCall(result, instr);
2053 2081
}
2054 2082

  
......
2083 2111

  
2084 2112

  
2085 2113
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2114
  LOperand* context = UseFixed(instr->context(), cp);
2086 2115
  LOperand* object = UseFixed(instr->object(), a0);
2087
  LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), v0);
2116
  LInstruction* result =
2117
      DefineFixed(new(zone()) LLoadNamedGeneric(context, object), v0);
2088 2118
  return MarkAsCall(result, instr);
2089 2119
}
2090 2120

  
......
2096 2126
}
2097 2127

  
2098 2128

  
2129
LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2130
  return DefineAsRegister(new(zone()) LLoadRoot);
2131
}
2132

  
2133

  
2099 2134
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
2100 2135
    HLoadExternalArrayPointer* instr) {
2101 2136
  LOperand* input = UseRegisterAtStart(instr->value());
......
2112 2147
  if (!instr->is_external()) {
2113 2148
    LOperand* obj = NULL;
2114 2149
    if (instr->representation().IsDouble()) {
2115
      obj = UseTempRegister(instr->elements());
2150
      obj = UseRegister(instr->elements());
2116 2151
    } else {
2117 2152
      ASSERT(instr->representation().IsSmiOrTagged());
2118 2153
      obj = UseRegisterAtStart(instr->elements());
......
2140 2175

  
2141 2176

  
2142 2177
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2178
  LOperand* context = UseFixed(instr->context(), cp);
2143 2179
  LOperand* object = UseFixed(instr->object(), a1);
2144 2180
  LOperand* key = UseFixed(instr->key(), a0);
2145 2181

  
2146 2182
  LInstruction* result =
2147
      DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), v0);
2183
      DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), v0);
2148 2184
  return MarkAsCall(result, instr);
2149 2185
}
2150 2186

  
2151 2187

  
2152 2188
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2153
  ElementsKind elements_kind = instr->elements_kind();
2154

  
2155 2189
  if (!instr->is_external()) {
2156 2190
    ASSERT(instr->elements()->representation().IsTagged());
2157 2191
    bool needs_write_barrier = instr->NeedsWriteBarrier();
......
2162 2196
    if (instr->value()->representation().IsDouble()) {
2163 2197
      object = UseRegisterAtStart(instr->elements());
2164 2198
      key = UseRegisterOrConstantAtStart(instr->key());
2165
      val = UseTempRegister(instr->value());
2199
      val = UseRegister(instr->value());
2166 2200
    } else {
2167 2201
      ASSERT(instr->value()->representation().IsSmiOrTagged());
2168
      object = UseTempRegister(instr->elements());
2169
      val = needs_write_barrier ? UseTempRegister(instr->value())
2170
          : UseRegisterAtStart(instr->value());
2171
      key = needs_write_barrier ? UseTempRegister(instr->key())
2172
          : UseRegisterOrConstantAtStart(instr->key());
2202
      if (needs_write_barrier) {
2203
        object = UseTempRegister(instr->elements());
2204
        val = UseTempRegister(instr->value());
2205
        key = UseTempRegister(instr->key());
2206
      } else {
2207
        object = UseRegisterAtStart(instr->elements());
2208
        val = UseRegisterAtStart(instr->value());
2209
        key = UseRegisterOrConstantAtStart(instr->key());
2210
      }
2173 2211
    }
2174 2212

  
2175 2213
    return new(zone()) LStoreKeyed(object, key, val);
......
2177 2215

  
2178 2216
  ASSERT(
2179 2217
      (instr->value()->representation().IsInteger32() &&
2180
       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2181
       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2218
       (instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) &&
2219
       (instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) ||
2182 2220
      (instr->value()->representation().IsDouble() &&
2183
       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2184
        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2221
       ((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) ||
2222
        (instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS))));
2185 2223
  ASSERT(instr->elements()->representation().IsExternal());
2186
  bool val_is_temp_register =
2187
      elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
2188
      elements_kind == EXTERNAL_FLOAT_ELEMENTS;
2189
  LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
2190
      : UseRegister(instr->value());
2224
  LOperand* val = UseRegister(instr->value());
2191 2225
  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2192 2226
  LOperand* external_pointer = UseRegister(instr->elements());
2193 2227

  
......
2196 2230

  
2197 2231

  
2198 2232
LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2233
  LOperand* context = UseFixed(instr->context(), cp);
2199 2234
  LOperand* obj = UseFixed(instr->object(), a2);
2200 2235
  LOperand* key = UseFixed(instr->key(), a1);
2201 2236
  LOperand* val = UseFixed(instr->value(), a0);
......
2204 2239
  ASSERT(instr->key()->representation().IsTagged());
2205 2240
  ASSERT(instr->value()->representation().IsTagged());
2206 2241

  
2207
  return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
2242
  return MarkAsCall(
2243
      new(zone()) LStoreKeyedGeneric(context, obj, key, val), instr);
2208 2244
}
2209 2245

  
2210 2246

  
......
2214 2250
  if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
2215 2251
    LOperand* new_map_reg = TempRegister();
2216 2252
    LTransitionElementsKind* result =
2217
        new(zone()) LTransitionElementsKind(object, new_map_reg);
2253
        new(zone()) LTransitionElementsKind(object, NULL, new_map_reg);
2218 2254
    return result;
2219 2255
  } else {
2256
    LOperand* context = UseFixed(instr->context(), cp);
2220 2257
    LTransitionElementsKind* result =
2221
        new(zone()) LTransitionElementsKind(object, NULL);
2258
        new(zone()) LTransitionElementsKind(object, context, NULL);
2222 2259
    return AssignPointerMap(result);
2223 2260
  }
2224 2261
}
......
2277 2314

  
2278 2315

  
2279 2316
LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2317
  LOperand* context = UseFixed(instr->context(), cp);
2280 2318
  LOperand* obj = UseFixed(instr->object(), a1);
2281 2319
  LOperand* val = UseFixed(instr->value(), a0);
2282 2320

  
2283
  LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
2321
  LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val);
2284 2322
  return MarkAsCall(result, instr);
2285 2323
}
2286 2324

  
2287 2325

  
2288 2326
LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2327
  LOperand* context = UseFixed(instr->context(), cp);
2289 2328
  LOperand* left = UseRegisterAtStart(instr->left());
2290 2329
  LOperand* right = UseRegisterAtStart(instr->right());
2291
  return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), v0),
2292
                    instr);
2330
  return MarkAsCall(
2331
      DefineFixed(new(zone()) LStringAdd(context, left, right), v0),
2332
      instr);
2293 2333
}
2294 2334

  
2295 2335

  
2296 2336
LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2297 2337
  LOperand* string = UseTempRegister(instr->string());
2298 2338
  LOperand* index = UseTempRegister(instr->index());
2299
  LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
2339
  LOperand* context = UseAny(instr->context());
2340
  LStringCharCodeAt* result =
2341
      new(zone()) LStringCharCodeAt(context, string, index);
2300 2342
  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2301 2343
}
2302 2344

  
2303 2345

  
2304 2346
LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2305 2347
  LOperand* char_code = UseRegister(instr->value());
2306
  LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
2348
  LOperand* context = UseAny(instr->context());
2349
  LStringCharFromCode* result =
2350
      new(zone()) LStringCharFromCode(context, char_code);
2307 2351
  return AssignPointerMap(DefineAsRegister(result));
2308 2352
}
2309 2353

  
2310 2354

  
2311 2355
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2312 2356
  info()->MarkAsDeferredCalling();
2357
  LOperand* context = UseAny(instr->context());
2313 2358
  LOperand* size = instr->size()->IsConstant()
2314 2359
      ? UseConstant(instr->size())
2315 2360
      : UseTempRegister(instr->size());
2316 2361
  LOperand* temp1 = TempRegister();
2317 2362
  LOperand* temp2 = TempRegister();
2318
  LAllocate* result = new(zone()) LAllocate(size, temp1, temp2);
2363
  LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
2319 2364
  return AssignPointerMap(DefineAsRegister(result));
2320 2365
}
2321 2366

  
2322 2367

  
2323 2368
LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2324
  return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, v0), instr);
2369
  LOperand* context = UseFixed(instr->context(), cp);
2370
  return MarkAsCall(
2371
      DefineFixed(new(zone()) LRegExpLiteral(context), v0), instr);
2325 2372
}
2326 2373

  
2327 2374

  
2328 2375
LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2329
  return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, v0), instr);
2376
  LOperand* context = UseFixed(instr->context(), cp);
2377
  return MarkAsCall(
2378
      DefineFixed(new(zone()) LFunctionLiteral(context), v0), instr);
2330 2379
}
2331 2380

  
2332 2381

  
......
2373 2422

  
2374 2423

  
2375 2424
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2376
  argument_count_ -= instr->argument_count();
2377
  return MarkAsCall(DefineFixed(new(zone()) LCallStub, v0), instr);
2425
  LOperand* context = UseFixed(instr->context(), cp);
2426
  return MarkAsCall(DefineFixed(new(zone()) LCallStub(context), v0), instr);
2378 2427
}
2379 2428

  
2380 2429

  
......
2419 2468

  
2420 2469

  
2421 2470
LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2422
  LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), a0));
2471
  LOperand* context = UseFixed(instr->context(), cp);
2472
  LTypeof* result = new(zone()) LTypeof(context, UseFixed(instr->value(), a0));
2423 2473
  return MarkAsCall(DefineFixed(result, v0), instr);
2424 2474
}
2425 2475

  
......
2458 2508

  
2459 2509
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2460 2510
  if (instr->is_function_entry()) {
2461
    return MarkAsCall(new(zone()) LStackCheck, instr);
2511
    LOperand* context = UseFixed(instr->context(), cp);
2512
    return MarkAsCall(new(zone()) LStackCheck(context), instr);
2462 2513
  } else {
2463 2514
    ASSERT(instr->is_backwards_branch());
2464
    return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
2515
    LOperand* context = UseAny(instr->context());
2516
    return AssignEnvironment(
2517
        AssignPointerMap(new(zone()) LStackCheck(context)));
2465 2518
  }
2466 2519
}
2467 2520

  
......
2494 2547
  if (env->entry()->arguments_pushed()) {
2495 2548
    int argument_count = env->arguments_environment()->parameter_count();
2496 2549
    pop = new(zone()) LDrop(argument_count);
2497
    argument_count_ -= argument_count;
2550
    ASSERT(instr->argument_delta() == -argument_count);
2498 2551
  }
2499 2552

  
2500 2553
  HEnvironment* outer = current_block_->last_environment()->
......
2506 2559

  
2507 2560

  
2508 2561
LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2562
  LOperand* context = UseFixed(instr->context(), cp);
2509 2563
  LOperand* object = UseFixed(instr->enumerable(), a0);
2510
  LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
2564
  LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
2511 2565
  return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
2512 2566
}
2513 2567

  

Also available in: Unified diff