Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(457)

Side by Side Diff: src/interpreter/bytecode-array-builder.cc

Issue 1613163002: [interpreter] Wide register support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Compilation fixes for gcc/msvc. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/bytecode-array-builder.h" 5 #include "src/interpreter/bytecode-array-builder.h"
6 6
7 namespace v8 { 7 namespace v8 {
8 namespace internal { 8 namespace internal {
9 namespace interpreter { 9 namespace interpreter {
10 10
11 class BytecodeArrayBuilder::PreviousBytecodeHelper { 11 class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED {
12 public: 12 public:
13 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) 13 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder)
14 : array_builder_(array_builder), 14 : array_builder_(array_builder),
15 previous_bytecode_start_(array_builder_.last_bytecode_start_) { 15 previous_bytecode_start_(array_builder_.last_bytecode_start_) {
16 // This helper is expected to be instantiated only when the last bytecode is 16 // This helper is expected to be instantiated only when the last bytecode is
17 // in the same basic block. 17 // in the same basic block.
18 DCHECK(array_builder_.LastBytecodeInSameBlock()); 18 DCHECK(array_builder_.LastBytecodeInSameBlock());
19 } 19 }
20 20
21 // Returns the previous bytecode in the same basic block. 21 // Returns the previous bytecode in the same basic block.
22 MUST_USE_RESULT Bytecode GetBytecode() const { 22 MUST_USE_RESULT Bytecode GetBytecode() const {
23 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); 23 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
24 return Bytecodes::FromByte( 24 return Bytecodes::FromByte(
25 array_builder_.bytecodes()->at(previous_bytecode_start_)); 25 array_builder_.bytecodes()->at(previous_bytecode_start_));
26 } 26 }
27 27
28 // Returns the operand at operand_index for the previous bytecode in the 28 // Returns the operand at operand_index for the previous bytecode in the
29 // same basic block. 29 // same basic block.
30 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { 30 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const {
31 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); 31 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
32 Bytecode bytecode = GetBytecode(); 32 Bytecode bytecode = GetBytecode();
33 DCHECK_GE(operand_index, 0); 33 DCHECK_GE(operand_index, 0);
34 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); 34 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode));
35 size_t operand_offset = 35 size_t operand_offset =
36 previous_bytecode_start_ + 36 previous_bytecode_start_ +
37 Bytecodes::GetOperandOffset(bytecode, operand_index); 37 Bytecodes::GetOperandOffset(bytecode, operand_index);
38 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); 38 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index);
39 switch (size) { 39 switch (size) {
40 default:
41 case OperandSize::kNone: 40 case OperandSize::kNone:
42 UNREACHABLE(); 41 UNREACHABLE();
42 break;
43 case OperandSize::kByte: 43 case OperandSize::kByte:
44 return static_cast<uint32_t>( 44 return static_cast<uint32_t>(
45 array_builder_.bytecodes()->at(operand_offset)); 45 array_builder_.bytecodes()->at(operand_offset));
46 case OperandSize::kShort: 46 case OperandSize::kShort:
47 uint16_t operand = 47 uint16_t operand =
48 (array_builder_.bytecodes()->at(operand_offset) << 8) + 48 (array_builder_.bytecodes()->at(operand_offset) << 8) +
49 array_builder_.bytecodes()->at(operand_offset + 1); 49 array_builder_.bytecodes()->at(operand_offset + 1);
50 return static_cast<uint32_t>(operand); 50 return static_cast<uint32_t>(operand);
51 } 51 }
52 return 0;
52 } 53 }
53 54
54 Handle<Object> GetConstantForIndexOperand(int operand_index) const { 55 Handle<Object> GetConstantForIndexOperand(int operand_index) const {
55 return array_builder_.constant_array_builder()->At( 56 return array_builder_.constant_array_builder()->At(
56 GetOperand(operand_index)); 57 GetOperand(operand_index));
57 } 58 }
58 59
59 private: 60 private:
60 const BytecodeArrayBuilder& array_builder_; 61 const BytecodeArrayBuilder& array_builder_;
61 size_t previous_bytecode_start_; 62 size_t previous_bytecode_start_;
(...skipping 10 matching lines...) Expand all
72 constant_array_builder_(isolate, zone), 73 constant_array_builder_(isolate, zone),
73 handler_table_builder_(isolate, zone), 74 handler_table_builder_(isolate, zone),
74 last_block_end_(0), 75 last_block_end_(0),
75 last_bytecode_start_(~0), 76 last_bytecode_start_(~0),
76 exit_seen_in_block_(false), 77 exit_seen_in_block_(false),
77 unbound_jumps_(0), 78 unbound_jumps_(0),
78 parameter_count_(-1), 79 parameter_count_(-1),
79 local_register_count_(-1), 80 local_register_count_(-1),
80 context_register_count_(-1), 81 context_register_count_(-1),
81 temporary_register_count_(0), 82 temporary_register_count_(0),
82 free_temporaries_(zone) {} 83 free_temporaries_(zone),
84 register_translator_(this) {}
83 85
84 86
85 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); } 87 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); }
86 88
87 89
88 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { 90 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) {
89 local_register_count_ = number_of_locals; 91 local_register_count_ = number_of_locals;
90 DCHECK_LE(context_register_count_, 0); 92 DCHECK_LE(context_register_count_, 0);
91 } 93 }
92 94
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 return temporary_register_count_ > 0 && first_temporary_register() <= reg && 143 return temporary_register_count_ > 0 && first_temporary_register() <= reg &&
142 reg <= last_temporary_register(); 144 reg <= last_temporary_register();
143 } 145 }
144 146
145 147
146 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { 148 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
147 DCHECK_EQ(bytecode_generated_, false); 149 DCHECK_EQ(bytecode_generated_, false);
148 EnsureReturn(); 150 EnsureReturn();
149 151
150 int bytecode_size = static_cast<int>(bytecodes_.size()); 152 int bytecode_size = static_cast<int>(bytecodes_.size());
151 int register_count = fixed_register_count() + temporary_register_count_; 153 int register_count =
154 fixed_and_temporary_register_count() + translation_register_count();
152 int frame_size = register_count * kPointerSize; 155 int frame_size = register_count * kPointerSize;
153 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); 156 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray();
154 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); 157 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable();
155 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray( 158 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray(
156 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), 159 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(),
157 constant_pool); 160 constant_pool);
158 output->set_handler_table(*handler_table); 161 output->set_handler_table(*handler_table);
159 bytecode_generated_ = true; 162 bytecode_generated_ = true;
160 return output; 163 return output;
161 } 164 }
162 165
163 166
164 template <size_t N> 167 template <size_t N>
165 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { 168 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) {
166 // Don't output dead code. 169 // Don't output dead code.
167 if (exit_seen_in_block_) return; 170 if (exit_seen_in_block_) return;
168 171
169 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); 172 int operand_count = static_cast<int>(N);
173 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count);
174
175 int register_operand_count = Bytecodes::NumberOfRegisterOperands(bytecode);
176 if (register_operand_count > 0) {
177 register_translator()->TranslateRegisters(bytecode, operands,
178 operand_count);
179 }
180
170 last_bytecode_start_ = bytecodes()->size(); 181 last_bytecode_start_ = bytecodes()->size();
171 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); 182 bytecodes()->push_back(Bytecodes::ToByte(bytecode));
172 for (int i = 0; i < static_cast<int>(N); i++) { 183 for (int i = 0; i < operand_count; i++) {
173 DCHECK(OperandIsValid(bytecode, i, operands[i])); 184 DCHECK(OperandIsValid(bytecode, i, operands[i]));
174 switch (Bytecodes::GetOperandSize(bytecode, i)) { 185 switch (Bytecodes::GetOperandSize(bytecode, i)) {
175 case OperandSize::kNone: 186 case OperandSize::kNone:
176 UNREACHABLE(); 187 UNREACHABLE();
188 break;
177 case OperandSize::kByte: 189 case OperandSize::kByte:
178 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); 190 bytecodes()->push_back(static_cast<uint8_t>(operands[i]));
179 break; 191 break;
180 case OperandSize::kShort: { 192 case OperandSize::kShort: {
181 uint8_t operand_bytes[2]; 193 uint8_t operand_bytes[2];
182 WriteUnalignedUInt16(operand_bytes, operands[i]); 194 WriteUnalignedUInt16(operand_bytes, operands[i]);
183 bytecodes()->insert(bytecodes()->end(), operand_bytes, 195 bytecodes()->insert(bytecodes()->end(), operand_bytes,
184 operand_bytes + 2); 196 operand_bytes + 2);
185 break; 197 break;
186 } 198 }
187 } 199 }
188 } 200 }
201
202 if (register_operand_count > 0) {
203 register_translator()->UntranslateRegisters();
rmcilroy 2016/01/25 12:12:05 Not sure about the naming of UntranslateRegisters.
oth 2016/01/25 16:51:56 Done as discussed TranslateInputRegisters/Translat
204 }
189 } 205 }
190 206
191 207
192 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, 208 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
193 uint32_t operand1, uint32_t operand2, 209 uint32_t operand1, uint32_t operand2,
194 uint32_t operand3) { 210 uint32_t operand3) {
195 uint32_t operands[] = {operand0, operand1, operand2, operand3}; 211 uint32_t operands[] = {operand0, operand1, operand2, operand3};
196 Output(bytecode, operands); 212 Output(bytecode, operands);
197 } 213 }
198 214
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 if (!IsRegisterInAccumulator(reg)) { 370 if (!IsRegisterInAccumulator(reg)) {
355 Output(Bytecode::kStar, reg.ToRawOperand()); 371 Output(Bytecode::kStar, reg.ToRawOperand());
356 } 372 }
357 return *this; 373 return *this;
358 } 374 }
359 375
360 376
361 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, 377 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
362 Register to) { 378 Register to) {
363 DCHECK(from != to); 379 DCHECK(from != to);
364 if (FitsInReg8Operand(to) && FitsInReg8Operand(from)) { 380 // Move bytecodes modify the stack. Chacking validity is essential.
rmcilroy 2016/01/25 12:12:05 I'm not sure what this comment means? I'm guessing
oth 2016/01/25 16:51:56 Have changed this to a DCHECK for the purpose of t
381 if (FitsInReg8Operand(from) && FitsInReg8Operand(to)) {
382 CHECK(RegisterIsValid(from, OperandType::kReg8) &&
383 RegisterIsValid(to, OperandType::kReg8));
365 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); 384 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand());
366 } else if (FitsInReg16Operand(to) && FitsInReg16Operand(from)) { 385 } else if (FitsInReg16Operand(from) && FitsInReg16Operand(to)) {
386 CHECK(RegisterIsValid(from, OperandType::kReg16) &&
387 RegisterIsValid(to, OperandType::kReg16));
367 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); 388 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand());
368 } else { 389 } else {
369 UNIMPLEMENTED(); 390 UNIMPLEMENTED();
370 } 391 }
371 return *this; 392 return *this;
372 } 393 }
373 394
374 395
396 void BytecodeArrayBuilder::MoveRegisterUntranslated(Register from,
397 Register to) {
398 // Move bytecodes modify the stack. Chacking validity is essential.
399 if (FitsInReg8OperandUntranslated(from)) {
400 CHECK(RegisterIsValid(from, OperandType::kReg8) &&
401 RegisterIsValid(to, OperandType::kReg16));
402 } else if (FitsInReg8OperandUntranslated(to)) {
403 CHECK(RegisterIsValid(from, OperandType::kReg16) &&
404 RegisterIsValid(to, OperandType::kReg8));
405 } else {
406 UNIMPLEMENTED();
407 }
408 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand());
409 }
410
411
375 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( 412 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(
376 const Handle<String> name, int feedback_slot, LanguageMode language_mode, 413 const Handle<String> name, int feedback_slot, LanguageMode language_mode,
377 TypeofMode typeof_mode) { 414 TypeofMode typeof_mode) {
378 // TODO(rmcilroy): Potentially store language and typeof information in an 415 // TODO(rmcilroy): Potentially store language and typeof information in an
379 // operand rather than having extra bytecodes. 416 // operand rather than having extra bytecodes.
380 Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode); 417 Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode);
381 size_t name_index = GetConstantPoolEntry(name); 418 size_t name_index = GetConstantPoolEntry(name);
382 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { 419 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
383 Output(bytecode, static_cast<uint8_t>(name_index), 420 Output(bytecode, static_cast<uint8_t>(name_index),
384 static_cast<uint8_t>(feedback_slot)); 421 static_cast<uint8_t>(feedback_slot));
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 } 1113 }
1077 1114
1078 1115
1079 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, 1116 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
1080 Register first_arg, 1117 Register first_arg,
1081 size_t arg_count) { 1118 size_t arg_count) {
1082 if (!first_arg.is_valid()) { 1119 if (!first_arg.is_valid()) {
1083 DCHECK_EQ(0u, arg_count); 1120 DCHECK_EQ(0u, arg_count);
1084 first_arg = Register(0); 1121 first_arg = Register(0);
1085 } 1122 }
1086
1087 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && 1123 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) &&
1088 FitsInIdx8Operand(arg_count)) { 1124 FitsInIdx8Operand(arg_count)) {
1089 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), 1125 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(),
1090 static_cast<uint8_t>(arg_count)); 1126 static_cast<uint8_t>(arg_count));
1091 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && 1127 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) &&
1092 FitsInIdx16Operand(arg_count)) { 1128 FitsInIdx16Operand(arg_count)) {
1093 Output(Bytecode::kNewWide, constructor.ToRawOperand(), 1129 Output(Bytecode::kNewWide, constructor.ToRawOperand(),
1094 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); 1130 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count));
1095 } else { 1131 } else {
1096 UNIMPLEMENTED(); 1132 UNIMPLEMENTED();
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 Output(Bytecode::kDeleteLookupSlot); 1210 Output(Bytecode::kDeleteLookupSlot);
1175 return *this; 1211 return *this;
1176 } 1212 }
1177 1213
1178 1214
1179 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { 1215 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
1180 return constant_array_builder()->Insert(object); 1216 return constant_array_builder()->Insert(object);
1181 } 1217 }
1182 1218
1183 1219
1220 void BytecodeArrayBuilder::ForgeTemporaryRegister() {
1221 temporary_register_count_++;
1222 }
1223
1224
1184 int BytecodeArrayBuilder::BorrowTemporaryRegister() { 1225 int BytecodeArrayBuilder::BorrowTemporaryRegister() {
1185 if (free_temporaries_.empty()) { 1226 if (free_temporaries_.empty()) {
1186 temporary_register_count_ += 1; 1227 ForgeTemporaryRegister();
1187 return last_temporary_register().index(); 1228 return last_temporary_register().index();
1188 } else { 1229 } else {
1189 auto pos = free_temporaries_.begin(); 1230 auto pos = free_temporaries_.begin();
1190 int retval = *pos; 1231 int retval = *pos;
1191 free_temporaries_.erase(pos); 1232 free_temporaries_.erase(pos);
1192 return retval; 1233 return retval;
1193 } 1234 }
1194 } 1235 }
1195 1236
1196 1237
1197 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index, 1238 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index,
1198 int end_index) { 1239 int end_index) {
1199 auto index = free_temporaries_.lower_bound(start_index); 1240 auto index = free_temporaries_.lower_bound(start_index);
1200 if (index == free_temporaries_.begin()) { 1241 if (index == free_temporaries_.begin()) {
1201 // If start_index is the first free register, check for a register 1242 // If start_index is the first free register, check for a register
1202 // greater than end_index. 1243 // greater than end_index.
1203 index = free_temporaries_.upper_bound(end_index); 1244 index = free_temporaries_.upper_bound(end_index);
1204 if (index == free_temporaries_.end()) { 1245 if (index == free_temporaries_.end()) {
1205 temporary_register_count_ += 1; 1246 ForgeTemporaryRegister();
1206 return last_temporary_register().index(); 1247 return last_temporary_register().index();
1207 } 1248 }
1208 } else { 1249 } else {
1209 // If there is a free register < start_index 1250 // If there is a free register < start_index
1210 index--; 1251 index--;
1211 } 1252 }
1212 1253
1213 int retval = *index; 1254 int retval = *index;
1214 free_temporaries_.erase(index); 1255 free_temporaries_.erase(index);
1215 return retval; 1256 return retval;
(...skipping 11 matching lines...) Expand all
1227 free_temporaries_.insert(reg_index); 1268 free_temporaries_.insert(reg_index);
1228 } 1269 }
1229 1270
1230 1271
1231 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( 1272 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters(
1232 size_t count) { 1273 size_t count) {
1233 if (count == 0) { 1274 if (count == 0) {
1234 return -1; 1275 return -1;
1235 } 1276 }
1236 1277
1278 // TODO(oth): replace use of set<> here for free_temporaries with a
1279 // more efficient structure. And/or partition into two searches -
1280 // one before the translation window and one after.
1281
1282 // A run will require at least |count| free temporaries.
1283 while (free_temporaries_.size() < count) {
1284 ForgeTemporaryRegister();
1285 free_temporaries_.insert(last_temporary_register().index());
1286 }
1287
1237 // Search within existing temporaries for a run. 1288 // Search within existing temporaries for a run.
1238 auto start = free_temporaries_.begin(); 1289 auto start = free_temporaries_.begin();
1239 size_t run_length = 0; 1290 size_t run_length = 0;
1240 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) { 1291 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) {
1241 if (*run_end != *start + static_cast<int>(run_length)) { 1292 int expected = *start + static_cast<int>(run_length);
1293 if (*run_end != expected) {
1242 start = run_end; 1294 start = run_end;
1243 run_length = 0; 1295 run_length = 0;
1244 } 1296 }
1297 Register reg_start(*start);
1298 Register reg_expected(expected);
1299 if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 &&
1300 RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) {
1301 // Run straddles the lower edge of the translation window. Registers
1302 // after the start of this boundary are displaced by the register
1303 // translator to provide a hole for translation. Runs either side
1304 // of the boundary are fine.
1305 start = run_end;
1306 run_length = 0;
1307 }
1245 if (++run_length == count) { 1308 if (++run_length == count) {
1246 return *start; 1309 return *start;
1247 } 1310 }
1248 } 1311 }
1249 1312
1250 // Continue run if possible across existing last temporary. 1313 // Continue run if possible across existing last temporary.
1251 if (temporary_register_count_ > 0 && 1314 if (temporary_register_count_ > 0 &&
1252 (start == free_temporaries_.end() || 1315 (start == free_temporaries_.end() ||
1253 *start + static_cast<int>(run_length) != 1316 *start + static_cast<int>(run_length) !=
1254 last_temporary_register().index() + 1)) { 1317 last_temporary_register().index() + 1)) {
1255 run_length = 0; 1318 run_length = 0;
1256 } 1319 }
1257 1320
1321 // Pad temporaries if extended run would cross translation boundary.
1322 Register reg_first(*start);
1323 Register reg_last(*start + static_cast<int>(count) - 1);
1324 DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first),
1325 RegisterTranslator::DistanceToTranslationWindow(reg_last));
1326 while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 &&
1327 RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) {
1328 ForgeTemporaryRegister();
1329 free_temporaries_.insert(last_temporary_register().index());
1330 start = --free_temporaries_.end();
1331 reg_first = Register(*start);
1332 reg_last = Register(*start + static_cast<int>(count) - 1);
1333 run_length = 0;
1334 }
1335
1258 // Ensure enough registers for run. 1336 // Ensure enough registers for run.
1259 while (run_length++ < count) { 1337 while (run_length++ < count) {
1260 temporary_register_count_++; 1338 ForgeTemporaryRegister();
1261 free_temporaries_.insert(last_temporary_register().index()); 1339 free_temporaries_.insert(last_temporary_register().index());
1262 } 1340 }
1263 return last_temporary_register().index() - static_cast<int>(count) + 1; 1341
1342 int run_start =
1343 last_temporary_register().index() - static_cast<int>(count) + 1;
1344 DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <=
1345 0 ||
1346 RegisterTranslator::DistanceToTranslationWindow(
1347 Register(run_start + static_cast<int>(count) - 1)) > 0);
1348 return run_start;
1264 } 1349 }
1265 1350
1266 1351
1267 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { 1352 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
1268 if (temporary_register_count_ > 0) { 1353 if (temporary_register_count_ > 0) {
1269 DCHECK(reg.index() >= first_temporary_register().index() && 1354 DCHECK(reg.index() >= first_temporary_register().index() &&
1270 reg.index() <= last_temporary_register().index()); 1355 reg.index() <= last_temporary_register().index());
1271 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); 1356 return free_temporaries_.find(reg.index()) == free_temporaries_.end();
1272 } else { 1357 } else {
1273 return false; 1358 return false;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 } 1409 }
1325 UNREACHABLE(); 1410 UNREACHABLE();
1326 return false; 1411 return false;
1327 } 1412 }
1328 1413
1329 1414
1330 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, 1415 bool BytecodeArrayBuilder::RegisterIsValid(Register reg,
1331 OperandType reg_type) const { 1416 OperandType reg_type) const {
1332 switch (Bytecodes::SizeOfOperand(reg_type)) { 1417 switch (Bytecodes::SizeOfOperand(reg_type)) {
1333 case OperandSize::kByte: 1418 case OperandSize::kByte:
1334 if (!FitsInReg8Operand(reg)) { return false; } 1419 if (!FitsInReg8OperandUntranslated(reg)) {
1420 return false;
1421 }
1335 break; 1422 break;
1336 case OperandSize::kShort: 1423 case OperandSize::kShort:
1337 if (!FitsInReg16Operand(reg)) { return false; } 1424 if (!FitsInReg16OperandUntranslated(reg)) {
1425 return false;
1426 }
1338 break; 1427 break;
1339 case OperandSize::kNone: 1428 case OperandSize::kNone:
1340 UNREACHABLE(); 1429 UNREACHABLE();
1341 return false; 1430 return false;
1342 } 1431 }
1343 1432
1344 if (reg.is_current_context() || reg.is_function_closure() || 1433 if (reg.is_current_context() || reg.is_function_closure() ||
1345 reg.is_new_target()) { 1434 reg.is_new_target()) {
1346 return true; 1435 return true;
1347 } else if (reg.is_parameter()) { 1436 } else if (reg.is_parameter()) {
1348 int parameter_index = reg.ToParameterIndex(parameter_count_); 1437 int parameter_index = reg.ToParameterIndex(parameter_count());
1349 return parameter_index >= 0 && parameter_index < parameter_count_; 1438 return parameter_index >= 0 && parameter_index < parameter_count();
1350 } else if (reg.index() < fixed_register_count()) {
1351 return true;
1352 } else { 1439 } else {
1353 return TemporaryRegisterIsLive(reg); 1440 int register_limit =
1441 (fixed_and_temporary_register_count() + translation_register_count());
1442 return reg.index() < register_limit;
rmcilroy 2016/01/25 12:12:05 Same comment as last time on this line - looks lik
oth 2016/01/25 16:51:56 No, brain melt. Fixed.
1354 } 1443 }
1355 } 1444 }
1356 1445
1357 1446
1358 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { 1447 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const {
1359 return last_bytecode_start_ < bytecodes()->size() && 1448 return last_bytecode_start_ < bytecodes()->size() &&
1360 last_bytecode_start_ >= last_block_end_; 1449 last_bytecode_start_ >= last_block_end_;
1361 } 1450 }
1362 1451
1363 1452
1364 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { 1453 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) {
1365 if (LastBytecodeInSameBlock()) { 1454 if (LastBytecodeInSameBlock()) {
1366 PreviousBytecodeHelper previous_bytecode(*this); 1455 PreviousBytecodeHelper previous_bytecode(*this);
1367 Bytecode bytecode = previous_bytecode.GetBytecode(); 1456 Bytecode bytecode = previous_bytecode.GetBytecode();
1368 if ((bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) && 1457 if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) {
1369 (reg == Register::FromOperand(previous_bytecode.GetOperand(0)))) { 1458 Register previous_reg =
1370 return true; 1459 Register::FromOperand(previous_bytecode.GetOperand(0));
1460 return previous_reg == reg;
1371 } 1461 }
1372 } 1462 }
1373 return false; 1463 return false;
1374 } 1464 }
1375 1465
1376 1466
1377 // static 1467 // static
1378 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { 1468 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
1379 switch (op) { 1469 switch (op) {
1380 case Token::Value::ADD: 1470 case Token::Value::ADD:
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 1763
1674 1764
1675 // static 1765 // static
1676 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { 1766 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) {
1677 return value <= static_cast<size_t>(kMaxUInt16); 1767 return value <= static_cast<size_t>(kMaxUInt16);
1678 } 1768 }
1679 1769
1680 1770
1681 // static 1771 // static
1682 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { 1772 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) {
1683 return kMinInt8 <= value.index() && value.index() <= kMaxInt8; 1773 return RegisterTranslator::FitsInReg8Operand(value);
1774 }
1775
1776
1777 // static
1778 bool BytecodeArrayBuilder::FitsInReg8OperandUntranslated(Register value) {
1779 return value.is_byte_operand();
1684 } 1780 }
1685 1781
1686 1782
1687 // static 1783 // static
1688 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { 1784 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) {
1689 return kMinInt16 <= value.index() && value.index() <= kMaxInt16; 1785 return RegisterTranslator::FitsInReg16Operand(value);
1786 }
1787
1788
1789 // static
1790 bool BytecodeArrayBuilder::FitsInReg16OperandUntranslated(Register value) {
1791 return value.is_short_operand();
1690 } 1792 }
1691 1793
1692 } // namespace interpreter 1794 } // namespace interpreter
1693 } // namespace internal 1795 } // namespace internal
1694 } // namespace v8 1796 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698