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

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: Rebase 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
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-array-iterator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_;
62 63
63 DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper); 64 DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper);
64 }; 65 };
65 66
66
67 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) 67 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone)
68 : isolate_(isolate), 68 : isolate_(isolate),
69 zone_(zone), 69 zone_(zone),
70 bytecodes_(zone), 70 bytecodes_(zone),
71 bytecode_generated_(false), 71 bytecode_generated_(false),
72 constant_array_builder_(isolate, zone), 72 constant_array_builder_(isolate, zone),
73 handler_table_builder_(isolate, zone), 73 handler_table_builder_(isolate, zone),
74 last_block_end_(0), 74 last_block_end_(0),
75 last_bytecode_start_(~0), 75 last_bytecode_start_(~0),
76 exit_seen_in_block_(false), 76 exit_seen_in_block_(false),
77 unbound_jumps_(0), 77 unbound_jumps_(0),
78 parameter_count_(-1), 78 parameter_count_(-1),
79 local_register_count_(-1), 79 local_register_count_(-1),
80 context_register_count_(-1), 80 context_register_count_(-1),
81 temporary_register_count_(0), 81 temporary_register_count_(0),
82 free_temporaries_(zone) {} 82 free_temporaries_(zone),
83 83 register_translator_(this) {}
84 84
85 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); } 85 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); }
86 86
87 87
88 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { 88 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) {
89 local_register_count_ = number_of_locals; 89 local_register_count_ = number_of_locals;
90 DCHECK_LE(context_register_count_, 0); 90 DCHECK_LE(context_register_count_, 0);
91 } 91 }
92 92
93 93
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 return temporary_register_count_ > 0 && first_temporary_register() <= reg && 141 return temporary_register_count_ > 0 && first_temporary_register() <= reg &&
142 reg <= last_temporary_register(); 142 reg <= last_temporary_register();
143 } 143 }
144 144
145 145
146 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { 146 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
147 DCHECK_EQ(bytecode_generated_, false); 147 DCHECK_EQ(bytecode_generated_, false);
148 EnsureReturn(); 148 EnsureReturn();
149 149
150 int bytecode_size = static_cast<int>(bytecodes_.size()); 150 int bytecode_size = static_cast<int>(bytecodes_.size());
151 int register_count = fixed_register_count() + temporary_register_count_; 151 int register_count =
152 fixed_and_temporary_register_count() + translation_register_count();
152 int frame_size = register_count * kPointerSize; 153 int frame_size = register_count * kPointerSize;
153 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); 154 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray();
154 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); 155 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable();
155 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray( 156 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray(
156 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), 157 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(),
157 constant_pool); 158 constant_pool);
158 output->set_handler_table(*handler_table); 159 output->set_handler_table(*handler_table);
159 bytecode_generated_ = true; 160 bytecode_generated_ = true;
160 return output; 161 return output;
161 } 162 }
162 163
163 164
164 template <size_t N> 165 template <size_t N>
165 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { 166 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) {
166 // Don't output dead code. 167 // Don't output dead code.
167 if (exit_seen_in_block_) return; 168 if (exit_seen_in_block_) return;
168 169
169 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); 170 int operand_count = static_cast<int>(N);
171 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count);
172
173 int register_operand_count = Bytecodes::NumberOfRegisterOperands(bytecode);
174 if (register_operand_count > 0) {
175 register_translator()->TranslateInputRegisters(bytecode, operands,
176 operand_count);
177 }
178
170 last_bytecode_start_ = bytecodes()->size(); 179 last_bytecode_start_ = bytecodes()->size();
171 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); 180 bytecodes()->push_back(Bytecodes::ToByte(bytecode));
172 for (int i = 0; i < static_cast<int>(N); i++) { 181 for (int i = 0; i < operand_count; i++) {
173 DCHECK(OperandIsValid(bytecode, i, operands[i])); 182 DCHECK(OperandIsValid(bytecode, i, operands[i]));
174 switch (Bytecodes::GetOperandSize(bytecode, i)) { 183 switch (Bytecodes::GetOperandSize(bytecode, i)) {
175 case OperandSize::kNone: 184 case OperandSize::kNone:
176 UNREACHABLE(); 185 UNREACHABLE();
186 break;
177 case OperandSize::kByte: 187 case OperandSize::kByte:
178 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); 188 bytecodes()->push_back(static_cast<uint8_t>(operands[i]));
179 break; 189 break;
180 case OperandSize::kShort: { 190 case OperandSize::kShort: {
181 uint8_t operand_bytes[2]; 191 uint8_t operand_bytes[2];
182 WriteUnalignedUInt16(operand_bytes, operands[i]); 192 WriteUnalignedUInt16(operand_bytes, operands[i]);
183 bytecodes()->insert(bytecodes()->end(), operand_bytes, 193 bytecodes()->insert(bytecodes()->end(), operand_bytes,
184 operand_bytes + 2); 194 operand_bytes + 2);
185 break; 195 break;
186 } 196 }
187 } 197 }
188 } 198 }
199
200 if (register_operand_count > 0) {
201 register_translator()->TranslateOutputRegisters();
202 }
189 } 203 }
190 204
191 205
192 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, 206 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
193 uint32_t operand1, uint32_t operand2, 207 uint32_t operand1, uint32_t operand2,
194 uint32_t operand3) { 208 uint32_t operand3) {
195 uint32_t operands[] = {operand0, operand1, operand2, operand3}; 209 uint32_t operands[] = {operand0, operand1, operand2, operand3};
196 Output(bytecode, operands); 210 Output(bytecode, operands);
197 } 211 }
198 212
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 if (!IsRegisterInAccumulator(reg)) { 368 if (!IsRegisterInAccumulator(reg)) {
355 Output(Bytecode::kStar, reg.ToRawOperand()); 369 Output(Bytecode::kStar, reg.ToRawOperand());
356 } 370 }
357 return *this; 371 return *this;
358 } 372 }
359 373
360 374
361 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, 375 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
362 Register to) { 376 Register to) {
363 DCHECK(from != to); 377 DCHECK(from != to);
364 if (FitsInReg8Operand(to) && FitsInReg8Operand(from)) { 378 if (FitsInReg8Operand(from) && FitsInReg8Operand(to)) {
365 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); 379 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand());
366 } else if (FitsInReg16Operand(to) && FitsInReg16Operand(from)) { 380 } else if (FitsInReg16Operand(from) && FitsInReg16Operand(to)) {
367 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); 381 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand());
368 } else { 382 } else {
369 UNIMPLEMENTED(); 383 UNIMPLEMENTED();
370 } 384 }
371 return *this; 385 return *this;
372 } 386 }
373 387
388 void BytecodeArrayBuilder::MoveRegisterUntranslated(Register from,
389 Register to) {
390 // Move bytecodes modify the stack. Checking validity is an
391 // essential mitigation against corrupting the stack.
392 if (FitsInReg8OperandUntranslated(from)) {
393 CHECK(RegisterIsValid(from, OperandType::kReg8) &&
394 RegisterIsValid(to, OperandType::kReg16));
395 } else if (FitsInReg8OperandUntranslated(to)) {
396 CHECK(RegisterIsValid(from, OperandType::kReg16) &&
397 RegisterIsValid(to, OperandType::kReg8));
398 } else {
399 UNIMPLEMENTED();
400 }
401 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand());
402 }
403
404 bool BytecodeArrayBuilder::RegisterOperandIsMovable(Bytecode bytecode,
405 int operand_index) {
406 // By design, we only support moving individual registers. There
407 // should be wide variants of such bytecodes instead to avoid the
408 // need for a large translation window.
409 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
410 if (operand_type != OperandType::kReg8 &&
411 operand_type != OperandType::kReg16) {
412 return false;
413 } else if (operand_index + 1 == Bytecodes::NumberOfOperands(bytecode)) {
414 return true;
415 } else {
416 OperandType next_operand_type =
417 Bytecodes::GetOperandType(bytecode, operand_index + 1);
418 return (next_operand_type != OperandType::kRegCount8 &&
419 next_operand_type != OperandType::kRegCount16);
420 }
421 }
374 422
375 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( 423 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(
376 const Handle<String> name, int feedback_slot, LanguageMode language_mode, 424 const Handle<String> name, int feedback_slot, LanguageMode language_mode,
377 TypeofMode typeof_mode) { 425 TypeofMode typeof_mode) {
378 // TODO(rmcilroy): Potentially store language and typeof information in an 426 // TODO(rmcilroy): Potentially store language and typeof information in an
379 // operand rather than having extra bytecodes. 427 // operand rather than having extra bytecodes.
380 Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode); 428 Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode);
381 size_t name_index = GetConstantPoolEntry(name); 429 size_t name_index = GetConstantPoolEntry(name);
382 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { 430 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
383 Output(bytecode, static_cast<uint8_t>(name_index), 431 Output(bytecode, static_cast<uint8_t>(name_index),
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 } 1124 }
1077 1125
1078 1126
1079 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, 1127 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
1080 Register first_arg, 1128 Register first_arg,
1081 size_t arg_count) { 1129 size_t arg_count) {
1082 if (!first_arg.is_valid()) { 1130 if (!first_arg.is_valid()) {
1083 DCHECK_EQ(0u, arg_count); 1131 DCHECK_EQ(0u, arg_count);
1084 first_arg = Register(0); 1132 first_arg = Register(0);
1085 } 1133 }
1086
1087 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && 1134 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) &&
1088 FitsInIdx8Operand(arg_count)) { 1135 FitsInIdx8Operand(arg_count)) {
1089 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), 1136 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(),
1090 static_cast<uint8_t>(arg_count)); 1137 static_cast<uint8_t>(arg_count));
1091 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && 1138 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) &&
1092 FitsInIdx16Operand(arg_count)) { 1139 FitsInIdx16Operand(arg_count)) {
1093 Output(Bytecode::kNewWide, constructor.ToRawOperand(), 1140 Output(Bytecode::kNewWide, constructor.ToRawOperand(),
1094 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); 1141 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count));
1095 } else { 1142 } else {
1096 UNIMPLEMENTED(); 1143 UNIMPLEMENTED();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 BytecodeArrayBuilder& BytecodeArrayBuilder::DeleteLookupSlot() { 1220 BytecodeArrayBuilder& BytecodeArrayBuilder::DeleteLookupSlot() {
1174 Output(Bytecode::kDeleteLookupSlot); 1221 Output(Bytecode::kDeleteLookupSlot);
1175 return *this; 1222 return *this;
1176 } 1223 }
1177 1224
1178 1225
1179 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { 1226 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
1180 return constant_array_builder()->Insert(object); 1227 return constant_array_builder()->Insert(object);
1181 } 1228 }
1182 1229
1230 void BytecodeArrayBuilder::ForgeTemporaryRegister() {
1231 temporary_register_count_++;
1232 }
1183 1233
1184 int BytecodeArrayBuilder::BorrowTemporaryRegister() { 1234 int BytecodeArrayBuilder::BorrowTemporaryRegister() {
1185 if (free_temporaries_.empty()) { 1235 if (free_temporaries_.empty()) {
1186 temporary_register_count_ += 1; 1236 ForgeTemporaryRegister();
1187 return last_temporary_register().index(); 1237 return last_temporary_register().index();
1188 } else { 1238 } else {
1189 auto pos = free_temporaries_.begin(); 1239 auto pos = free_temporaries_.begin();
1190 int retval = *pos; 1240 int retval = *pos;
1191 free_temporaries_.erase(pos); 1241 free_temporaries_.erase(pos);
1192 return retval; 1242 return retval;
1193 } 1243 }
1194 } 1244 }
1195 1245
1196 1246
1197 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index, 1247 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index,
1198 int end_index) { 1248 int end_index) {
1199 auto index = free_temporaries_.lower_bound(start_index); 1249 auto index = free_temporaries_.lower_bound(start_index);
1200 if (index == free_temporaries_.begin()) { 1250 if (index == free_temporaries_.begin()) {
1201 // If start_index is the first free register, check for a register 1251 // If start_index is the first free register, check for a register
1202 // greater than end_index. 1252 // greater than end_index.
1203 index = free_temporaries_.upper_bound(end_index); 1253 index = free_temporaries_.upper_bound(end_index);
1204 if (index == free_temporaries_.end()) { 1254 if (index == free_temporaries_.end()) {
1205 temporary_register_count_ += 1; 1255 ForgeTemporaryRegister();
1206 return last_temporary_register().index(); 1256 return last_temporary_register().index();
1207 } 1257 }
1208 } else { 1258 } else {
1209 // If there is a free register < start_index 1259 // If there is a free register < start_index
1210 index--; 1260 index--;
1211 } 1261 }
1212 1262
1213 int retval = *index; 1263 int retval = *index;
1214 free_temporaries_.erase(index); 1264 free_temporaries_.erase(index);
1215 return retval; 1265 return retval;
(...skipping 11 matching lines...) Expand all
1227 free_temporaries_.insert(reg_index); 1277 free_temporaries_.insert(reg_index);
1228 } 1278 }
1229 1279
1230 1280
1231 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( 1281 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters(
1232 size_t count) { 1282 size_t count) {
1233 if (count == 0) { 1283 if (count == 0) {
1234 return -1; 1284 return -1;
1235 } 1285 }
1236 1286
1287 // TODO(oth): replace use of set<> here for free_temporaries with a
1288 // more efficient structure. And/or partition into two searches -
1289 // one before the translation window and one after.
1290
1291 // A run will require at least |count| free temporaries.
1292 while (free_temporaries_.size() < count) {
1293 ForgeTemporaryRegister();
1294 free_temporaries_.insert(last_temporary_register().index());
1295 }
1296
1237 // Search within existing temporaries for a run. 1297 // Search within existing temporaries for a run.
1238 auto start = free_temporaries_.begin(); 1298 auto start = free_temporaries_.begin();
1239 size_t run_length = 0; 1299 size_t run_length = 0;
1240 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) { 1300 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) {
1241 if (*run_end != *start + static_cast<int>(run_length)) { 1301 int expected = *start + static_cast<int>(run_length);
1302 if (*run_end != expected) {
1242 start = run_end; 1303 start = run_end;
1243 run_length = 0; 1304 run_length = 0;
1244 } 1305 }
1306 Register reg_start(*start);
1307 Register reg_expected(expected);
1308 if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 &&
1309 RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) {
1310 // Run straddles the lower edge of the translation window. Registers
1311 // after the start of this boundary are displaced by the register
1312 // translator to provide a hole for translation. Runs either side
1313 // of the boundary are fine.
1314 start = run_end;
1315 run_length = 0;
1316 }
1245 if (++run_length == count) { 1317 if (++run_length == count) {
1246 return *start; 1318 return *start;
1247 } 1319 }
1248 } 1320 }
1249 1321
1250 // Continue run if possible across existing last temporary. 1322 // Continue run if possible across existing last temporary.
1251 if (temporary_register_count_ > 0 && 1323 if (temporary_register_count_ > 0 &&
1252 (start == free_temporaries_.end() || 1324 (start == free_temporaries_.end() ||
1253 *start + static_cast<int>(run_length) != 1325 *start + static_cast<int>(run_length) !=
1254 last_temporary_register().index() + 1)) { 1326 last_temporary_register().index() + 1)) {
1255 run_length = 0; 1327 run_length = 0;
1256 } 1328 }
1257 1329
1330 // Pad temporaries if extended run would cross translation boundary.
1331 Register reg_first(*start);
1332 Register reg_last(*start + static_cast<int>(count) - 1);
1333 DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first),
1334 RegisterTranslator::DistanceToTranslationWindow(reg_last));
1335 while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 &&
1336 RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) {
1337 ForgeTemporaryRegister();
1338 free_temporaries_.insert(last_temporary_register().index());
1339 start = --free_temporaries_.end();
1340 reg_first = Register(*start);
1341 reg_last = Register(*start + static_cast<int>(count) - 1);
1342 run_length = 0;
1343 }
1344
1258 // Ensure enough registers for run. 1345 // Ensure enough registers for run.
1259 while (run_length++ < count) { 1346 while (run_length++ < count) {
1260 temporary_register_count_++; 1347 ForgeTemporaryRegister();
1261 free_temporaries_.insert(last_temporary_register().index()); 1348 free_temporaries_.insert(last_temporary_register().index());
1262 } 1349 }
1263 return last_temporary_register().index() - static_cast<int>(count) + 1; 1350
1351 int run_start =
1352 last_temporary_register().index() - static_cast<int>(count) + 1;
1353 DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <=
1354 0 ||
1355 RegisterTranslator::DistanceToTranslationWindow(
1356 Register(run_start + static_cast<int>(count) - 1)) > 0);
1357 return run_start;
1264 } 1358 }
1265 1359
1266 1360
1267 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { 1361 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
1268 if (temporary_register_count_ > 0) { 1362 if (temporary_register_count_ > 0) {
1269 DCHECK(reg.index() >= first_temporary_register().index() && 1363 DCHECK(reg.index() >= first_temporary_register().index() &&
1270 reg.index() <= last_temporary_register().index()); 1364 reg.index() <= last_temporary_register().index());
1271 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); 1365 return free_temporaries_.find(reg.index()) == free_temporaries_.end();
1272 } else { 1366 } else {
1273 return false; 1367 return false;
1274 } 1368 }
1275 } 1369 }
1276 1370
1277 1371
1278 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, 1372 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
1279 uint32_t operand_value) const { 1373 uint32_t operand_value) const {
1280 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); 1374 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
1281 switch (operand_type) { 1375 switch (operand_type) {
1282 case OperandType::kNone: 1376 case OperandType::kNone:
1283 return false; 1377 return false;
1284 case OperandType::kRegCount16: 1378 case OperandType::kRegCount16: {
1379 // Expect kRegCount16 is part of a range previous operand is a
1380 // valid operand to start a range.
1381 if (operand_index > 0) {
1382 OperandType previous_operand_type =
1383 Bytecodes::GetOperandType(bytecode, operand_index - 1);
1384 return ((previous_operand_type == OperandType::kMaybeReg16 ||
1385 previous_operand_type == OperandType::kReg16) &&
1386 static_cast<uint16_t>(operand_value) == operand_value);
1387 } else {
1388 return false;
1389 }
1390 }
1391 case OperandType::kRegCount8: {
1392 // Expect kRegCount8 is part of a range previous operand is a
1393 // valid operand to start a range.
1394 if (operand_index > 0) {
1395 OperandType previous_operand_type =
1396 Bytecodes::GetOperandType(bytecode, operand_index - 1);
1397 return ((previous_operand_type == OperandType::kMaybeReg8 ||
1398 previous_operand_type == OperandType::kReg8 ||
1399 previous_operand_type == OperandType::kMaybeReg16) &&
1400 static_cast<uint8_t>(operand_value) == operand_value);
1401 } else {
1402 return false;
1403 }
1404 }
1285 case OperandType::kIdx16: 1405 case OperandType::kIdx16:
1286 return static_cast<uint16_t>(operand_value) == operand_value; 1406 return static_cast<uint16_t>(operand_value) == operand_value;
1287 case OperandType::kRegCount8:
1288 case OperandType::kImm8: 1407 case OperandType::kImm8:
1289 case OperandType::kIdx8: 1408 case OperandType::kIdx8:
1290 return static_cast<uint8_t>(operand_value) == operand_value; 1409 return static_cast<uint8_t>(operand_value) == operand_value;
1291 case OperandType::kMaybeReg8: 1410 case OperandType::kMaybeReg8:
1292 if (operand_value == 0) { 1411 if (operand_value == 0) {
1293 return true; 1412 return true;
1294 } 1413 }
1295 // Fall-through to kReg8 case. 1414 // Fall-through to kReg8 case.
1296 case OperandType::kReg8: 1415 case OperandType::kReg8:
1297 return RegisterIsValid(Register::FromRawOperand(operand_value), 1416 return RegisterIsValid(Register::FromRawOperand(operand_value),
(...skipping 24 matching lines...) Expand all
1322 return RegisterIsValid(reg, operand_type); 1441 return RegisterIsValid(reg, operand_type);
1323 } 1442 }
1324 } 1443 }
1325 UNREACHABLE(); 1444 UNREACHABLE();
1326 return false; 1445 return false;
1327 } 1446 }
1328 1447
1329 1448
1330 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, 1449 bool BytecodeArrayBuilder::RegisterIsValid(Register reg,
1331 OperandType reg_type) const { 1450 OperandType reg_type) const {
1451 if (!reg.is_valid()) {
1452 return false;
1453 }
1454
1332 switch (Bytecodes::SizeOfOperand(reg_type)) { 1455 switch (Bytecodes::SizeOfOperand(reg_type)) {
1333 case OperandSize::kByte: 1456 case OperandSize::kByte:
1334 if (!FitsInReg8Operand(reg)) { return false; } 1457 if (!FitsInReg8OperandUntranslated(reg)) {
1458 return false;
1459 }
1335 break; 1460 break;
1336 case OperandSize::kShort: 1461 case OperandSize::kShort:
1337 if (!FitsInReg16Operand(reg)) { return false; } 1462 if (!FitsInReg16OperandUntranslated(reg)) {
1463 return false;
1464 }
1338 break; 1465 break;
1339 case OperandSize::kNone: 1466 case OperandSize::kNone:
1340 UNREACHABLE(); 1467 UNREACHABLE();
1341 return false; 1468 return false;
1342 } 1469 }
1343 1470
1344 if (reg.is_current_context() || reg.is_function_closure() || 1471 if (reg.is_current_context() || reg.is_function_closure() ||
1345 reg.is_new_target()) { 1472 reg.is_new_target()) {
1346 return true; 1473 return true;
1347 } else if (reg.is_parameter()) { 1474 } else if (reg.is_parameter()) {
1348 int parameter_index = reg.ToParameterIndex(parameter_count_); 1475 int parameter_index = reg.ToParameterIndex(parameter_count());
1349 return parameter_index >= 0 && parameter_index < parameter_count_; 1476 return parameter_index >= 0 && parameter_index < parameter_count();
1350 } else if (reg.index() < fixed_register_count()) { 1477 } else if (RegisterTranslator::InTranslationWindow(reg)) {
1351 return true; 1478 return translation_register_count() > 0;
1352 } else { 1479 } else {
1353 return TemporaryRegisterIsLive(reg); 1480 reg = RegisterTranslator::UntranslateRegister(reg);
1481 if (reg.index() < fixed_register_count()) {
1482 return true;
1483 } else {
1484 return TemporaryRegisterIsLive(reg);
1485 }
1354 } 1486 }
1355 } 1487 }
1356 1488
1357 1489
1358 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { 1490 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const {
1359 return last_bytecode_start_ < bytecodes()->size() && 1491 return last_bytecode_start_ < bytecodes()->size() &&
1360 last_bytecode_start_ >= last_block_end_; 1492 last_bytecode_start_ >= last_block_end_;
1361 } 1493 }
1362 1494
1363 1495
1364 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { 1496 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) {
1365 if (LastBytecodeInSameBlock()) { 1497 if (LastBytecodeInSameBlock()) {
1366 PreviousBytecodeHelper previous_bytecode(*this); 1498 PreviousBytecodeHelper previous_bytecode(*this);
1367 Bytecode bytecode = previous_bytecode.GetBytecode(); 1499 Bytecode bytecode = previous_bytecode.GetBytecode();
1368 if ((bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) && 1500 if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) {
1369 (reg == Register::FromOperand(previous_bytecode.GetOperand(0)))) { 1501 Register previous_reg =
1370 return true; 1502 Register::FromOperand(previous_bytecode.GetOperand(0));
1503 return previous_reg == reg;
1371 } 1504 }
1372 } 1505 }
1373 return false; 1506 return false;
1374 } 1507 }
1375 1508
1376 1509
1377 // static 1510 // static
1378 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { 1511 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
1379 switch (op) { 1512 switch (op) {
1380 case Token::Value::ADD: 1513 case Token::Value::ADD:
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 1806
1674 1807
1675 // static 1808 // static
1676 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { 1809 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) {
1677 return value <= static_cast<size_t>(kMaxUInt16); 1810 return value <= static_cast<size_t>(kMaxUInt16);
1678 } 1811 }
1679 1812
1680 1813
1681 // static 1814 // static
1682 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { 1815 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) {
1683 return kMinInt8 <= value.index() && value.index() <= kMaxInt8; 1816 return RegisterTranslator::FitsInReg8Operand(value);
1817 }
1818
1819 // static
1820 bool BytecodeArrayBuilder::FitsInReg8OperandUntranslated(Register value) {
1821 return value.is_byte_operand();
1684 } 1822 }
1685 1823
1686 1824
1687 // static 1825 // static
1688 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { 1826 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) {
1689 return kMinInt16 <= value.index() && value.index() <= kMaxInt16; 1827 return RegisterTranslator::FitsInReg16Operand(value);
1828 }
1829
1830 // static
1831 bool BytecodeArrayBuilder::FitsInReg16OperandUntranslated(Register value) {
1832 return value.is_short_operand();
1690 } 1833 }
1691 1834
1692 } // namespace interpreter 1835 } // namespace interpreter
1693 } // namespace internal 1836 } // namespace internal
1694 } // namespace v8 1837 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-array-iterator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698