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

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

Issue 1343363002: [Interpreter] Basic flow control. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix missing int cast for size_t. Created 5 years, 2 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
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 } 69 }
70 70
71 Handle<BytecodeArray> output = 71 Handle<BytecodeArray> output =
72 factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size, 72 factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size,
73 parameter_count_, constant_pool); 73 parameter_count_, constant_pool);
74 bytecode_generated_ = true; 74 bytecode_generated_ = true;
75 return output; 75 return output;
76 } 76 }
77 77
78 78
79 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value binop, 79 template <size_t N>
80 void BytecodeArrayBuilder::Output(uint8_t(&bytes)[N]) {
81 DCHECK_EQ(Bytecodes::NumberOfOperands(Bytecodes::FromByte(bytes[0])), N - 1);
82 for (int i = 1; i < static_cast<int>(N); i++) {
83 DCHECK(OperandIsValid(Bytecodes::FromByte(bytes[0]), i - 1, bytes[i]));
84 }
85 bytecodes()->insert(bytecodes()->end(), bytes, bytes + N);
86 }
87
88
89 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0,
90 uint8_t operand1, uint8_t operand2) {
91 uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0, operand1, operand2};
92 Output(bytes);
93 }
94
95
96 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0,
97 uint8_t operand1) {
98 uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0, operand1};
99 Output(bytes);
100 }
101
102
103 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0) {
104 uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0};
105 Output(bytes);
106 }
107
108
109 void BytecodeArrayBuilder::Output(Bytecode bytecode) {
110 uint8_t bytes[] = {Bytecodes::ToByte(bytecode)};
111 Output(bytes);
112 }
113
114
115 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
80 Register reg) { 116 Register reg) {
81 Output(BytecodeForBinaryOperation(binop), reg.ToOperand()); 117 Output(BytecodeForBinaryOperation(op), reg.ToOperand());
82 return *this; 118 return *this;
83 } 119 }
84 120
121
122 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
123 Token::Value op, Register reg, LanguageMode language_mode) {
124 if (!is_sloppy(language_mode)) {
125 UNIMPLEMENTED();
126 }
127
128 Output(BytecodeForCompareOperation(op), reg.ToOperand());
129 return *this;
130 }
131
85 132
86 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( 133 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
87 v8::internal::Smi* smi) { 134 v8::internal::Smi* smi) {
88 int32_t raw_smi = smi->value(); 135 int32_t raw_smi = smi->value();
89 if (raw_smi == 0) { 136 if (raw_smi == 0) {
90 Output(Bytecode::kLdaZero); 137 Output(Bytecode::kLdaZero);
91 } else if (raw_smi >= -128 && raw_smi <= 127) { 138 } else if (raw_smi >= -128 && raw_smi <= 127) {
92 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); 139 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi));
93 } else { 140 } else {
94 LoadLiteral(Handle<Object>(smi, isolate_)); 141 LoadLiteral(Handle<Object>(smi, isolate_));
95 } 142 }
96 return *this; 143 return *this;
97 } 144 }
98 145
99 146
100 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { 147 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
101 size_t entry = GetConstantPoolEntry(object); 148 size_t entry = GetConstantPoolEntry(object);
102 if (FitsInByteOperand(entry)) { 149 if (FitsInIdxOperand(entry)) {
103 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); 150 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry));
104 } else { 151 } else {
105 UNIMPLEMENTED(); 152 UNIMPLEMENTED();
106 } 153 }
107 return *this; 154 return *this;
108 } 155 }
109 156
110 157
111 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { 158 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
112 Output(Bytecode::kLdaUndefined); 159 Output(Bytecode::kLdaUndefined);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 return *this; 198 return *this;
152 } 199 }
153 200
154 201
155 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( 202 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
156 Register object, int feedback_slot, LanguageMode language_mode) { 203 Register object, int feedback_slot, LanguageMode language_mode) {
157 if (!is_sloppy(language_mode)) { 204 if (!is_sloppy(language_mode)) {
158 UNIMPLEMENTED(); 205 UNIMPLEMENTED();
159 } 206 }
160 207
161 if (FitsInByteOperand(feedback_slot)) { 208 if (FitsInIdxOperand(feedback_slot)) {
162 Output(Bytecode::kLoadIC, object.ToOperand(), 209 Output(Bytecode::kLoadIC, object.ToOperand(),
163 static_cast<uint8_t>(feedback_slot)); 210 static_cast<uint8_t>(feedback_slot));
164 } else { 211 } else {
165 UNIMPLEMENTED(); 212 UNIMPLEMENTED();
166 } 213 }
167 return *this; 214 return *this;
168 } 215 }
169 216
170 217
171 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( 218 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
172 Register object, int feedback_slot, LanguageMode language_mode) { 219 Register object, int feedback_slot, LanguageMode language_mode) {
173 if (!is_sloppy(language_mode)) { 220 if (!is_sloppy(language_mode)) {
174 UNIMPLEMENTED(); 221 UNIMPLEMENTED();
175 } 222 }
176 223
177 if (FitsInByteOperand(feedback_slot)) { 224 if (FitsInIdxOperand(feedback_slot)) {
178 Output(Bytecode::kKeyedLoadIC, object.ToOperand(), 225 Output(Bytecode::kKeyedLoadIC, object.ToOperand(),
179 static_cast<uint8_t>(feedback_slot)); 226 static_cast<uint8_t>(feedback_slot));
180 } else { 227 } else {
181 UNIMPLEMENTED(); 228 UNIMPLEMENTED();
182 } 229 }
183 return *this; 230 return *this;
184 } 231 }
185 232
186 233
187 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( 234 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
188 Register object, Register name, int feedback_slot, 235 Register object, Register name, int feedback_slot,
189 LanguageMode language_mode) { 236 LanguageMode language_mode) {
190 if (!is_sloppy(language_mode)) { 237 if (!is_sloppy(language_mode)) {
191 UNIMPLEMENTED(); 238 UNIMPLEMENTED();
192 } 239 }
193 240
194 if (FitsInByteOperand(feedback_slot)) { 241 if (FitsInIdxOperand(feedback_slot)) {
195 Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(), 242 Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(),
196 static_cast<uint8_t>(feedback_slot)); 243 static_cast<uint8_t>(feedback_slot));
197 } else { 244 } else {
198 UNIMPLEMENTED(); 245 UNIMPLEMENTED();
199 } 246 }
200 return *this; 247 return *this;
201 } 248 }
202 249
203 250
204 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( 251 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
205 Register object, Register key, int feedback_slot, 252 Register object, Register key, int feedback_slot,
206 LanguageMode language_mode) { 253 LanguageMode language_mode) {
207 if (!is_sloppy(language_mode)) { 254 if (!is_sloppy(language_mode)) {
208 UNIMPLEMENTED(); 255 UNIMPLEMENTED();
209 } 256 }
210 257
211 if (FitsInByteOperand(feedback_slot)) { 258 if (FitsInIdxOperand(feedback_slot)) {
212 Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(), 259 Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(),
213 static_cast<uint8_t>(feedback_slot)); 260 static_cast<uint8_t>(feedback_slot));
214 } else { 261 } else {
215 UNIMPLEMENTED(); 262 UNIMPLEMENTED();
216 } 263 }
217 return *this; 264 return *this;
218 } 265 }
219 266
220 267
268 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() {
269 // TODO(oth): Consider peeking at previous bytecode to see if it
270 // outputs a boolean value to the accumulator, if so this
271 // instruction can be elided. Similarly if it's a Load instruction
272 // change the instruction to basic true/false cast. Need to be
273 // careful with backwards branches though might only have
274 // troublesome cases in handwritten bytecode, but can check for
275 // unbound labels bound before this point to spot back branch
276 // targets.
277 Output(Bytecode::kCastToBoolean);
278 return *this;
279 }
280
281
282 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
283 if (label->is_forward_target()) {
284 // An earlier jump instruction refers to this label. Update it's location.
285 PatchJump(bytecodes()->end(), bytecodes()->begin() + label->offset());
286 // Now treat as if the label will only be back referred to.
287 }
288 label->bind_to(bytecodes()->size());
289 return *this;
290 }
291
292
293 // static
294 bool BytecodeArrayBuilder::IsJumpWithSmi8Operand(Bytecode jump_bytecode) {
295 return jump_bytecode == Bytecode::kJump ||
296 jump_bytecode == Bytecode::kJumpIfTrue ||
297 jump_bytecode == Bytecode::kJumpIfFalse;
298 }
299
300
301 // static
302 Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand(
303 Bytecode jump_bytecode) {
304 switch (jump_bytecode) {
305 case Bytecode::kJump:
306 return Bytecode::kJumpConstant;
307 case Bytecode::kJumpIfTrue:
308 return Bytecode::kJumpIfTrueConstant;
309 case Bytecode::kJumpIfFalse:
310 return Bytecode::kJumpIfFalseConstant;
311 default:
312 UNREACHABLE();
313 return Bytecode::kJumpConstant;
314 }
315 }
316
317
318 void BytecodeArrayBuilder::PatchJump(
319 const ZoneVector<uint8_t>::iterator& jump_target,
320 ZoneVector<uint8_t>::iterator jump_location) {
321 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
322 DCHECK(IsJumpWithSmi8Operand(jump_bytecode));
323 DCHECK_EQ(Bytecodes::Size(jump_bytecode), 2);
324 int delta = static_cast<int>(jump_target - jump_location);
325 DCHECK_GE(delta, 0);
326 if (FitsInImm8Operand(delta)) {
327 // Just update the operand
328 jump_location++;
329 *jump_location = static_cast<uint8_t>(delta);
330 } else {
331 // Update the jump type and operand
332 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate()));
333 if (FitsInIdxOperand(entry)) {
334 *jump_location++ =
335 Bytecodes::ToByte(GetJumpWithConstantOperand(jump_bytecode));
336 *jump_location = static_cast<uint8_t>(entry);
337 } else {
338 UNIMPLEMENTED();
339 }
340 }
341 }
342
343
344 void BytecodeArrayBuilder::OutputJump(
345 Bytecode jump_bytecode, const ZoneVector<uint8_t>::iterator& jump_target) {
346 DCHECK(IsJumpWithSmi8Operand(jump_bytecode));
347
348 int delta = static_cast<int>(jump_target - bytecodes()->end());
349 if (FitsInImm8Operand(delta)) {
350 Output(jump_bytecode, static_cast<uint8_t>(delta));
351 } else {
352 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate()));
353 if (FitsInIdxOperand(entry)) {
354 Output(GetJumpWithConstantOperand(jump_bytecode),
355 static_cast<uint8_t>(entry));
356 } else {
357 UNIMPLEMENTED();
358 }
359 }
360 }
361
362
363 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(Bytecode jump_bytecode,
364 BytecodeLabel* label) {
365 if (label->is_bound()) {
366 // Label has been bound already so this is a backwards jump.
367 OutputJump(jump_bytecode, bytecodes()->begin() + label->offset());
368 } else {
369 // Label has not yet been bound so this is a forward reference
370 // that will be patched when the label is bound.
371 label->set_referrer(bytecodes()->size());
372 OutputJump(jump_bytecode, bytecodes()->end());
373 }
374 return *this;
375 }
376
377
378 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
379 return Jump(Bytecode::kJump, label);
380 }
381
382
383 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
384 return Jump(Bytecode::kJumpIfTrue, label);
385 }
386
387
388 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
389 return Jump(Bytecode::kJumpIfFalse, label);
390 }
391
392
221 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { 393 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
222 Output(Bytecode::kReturn); 394 Output(Bytecode::kReturn);
223 return *this; 395 return *this;
224 } 396 }
225 397
226 398
227 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, 399 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
228 Register receiver, 400 Register receiver,
229 size_t arg_count) { 401 size_t arg_count) {
230 if (FitsInByteOperand(arg_count)) { 402 if (FitsInIdxOperand(arg_count)) {
231 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), 403 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(),
232 static_cast<uint8_t>(arg_count)); 404 static_cast<uint8_t>(arg_count));
233 } else { 405 } else {
234 UNIMPLEMENTED(); 406 UNIMPLEMENTED();
235 } 407 }
236 return *this; 408 return *this;
237 } 409 }
238 410
239 411
240 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { 412 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 } else { 464 } else {
293 return (reg.index() >= 0 && reg.index() < temporary_register_next_); 465 return (reg.index() >= 0 && reg.index() < temporary_register_next_);
294 } 466 }
295 } 467 }
296 } 468 }
297 UNREACHABLE(); 469 UNREACHABLE();
298 return false; 470 return false;
299 } 471 }
300 472
301 473
302 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0,
303 uint8_t operand1, uint8_t operand2) {
304 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3);
305 DCHECK(OperandIsValid(bytecode, 0, operand0) &&
306 OperandIsValid(bytecode, 1, operand1) &&
307 OperandIsValid(bytecode, 2, operand2));
308 bytecodes_.push_back(Bytecodes::ToByte(bytecode));
309 bytecodes_.push_back(operand0);
310 bytecodes_.push_back(operand1);
311 bytecodes_.push_back(operand2);
312 }
313
314
315 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0,
316 uint8_t operand1) {
317 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2);
318 DCHECK(OperandIsValid(bytecode, 0, operand0) &&
319 OperandIsValid(bytecode, 1, operand1));
320 bytecodes_.push_back(Bytecodes::ToByte(bytecode));
321 bytecodes_.push_back(operand0);
322 bytecodes_.push_back(operand1);
323 }
324
325
326 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0) {
327 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
328 DCHECK(OperandIsValid(bytecode, 0, operand0));
329 bytecodes_.push_back(Bytecodes::ToByte(bytecode));
330 bytecodes_.push_back(operand0);
331 }
332
333
334 void BytecodeArrayBuilder::Output(Bytecode bytecode) {
335 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
336 bytecodes_.push_back(Bytecodes::ToByte(bytecode));
337 }
338
339
340 // static 474 // static
341 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { 475 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
342 switch (op) { 476 switch (op) {
343 case Token::Value::ADD: 477 case Token::Value::ADD:
344 return Bytecode::kAdd; 478 return Bytecode::kAdd;
345 case Token::Value::SUB: 479 case Token::Value::SUB:
346 return Bytecode::kSub; 480 return Bytecode::kSub;
347 case Token::Value::MUL: 481 case Token::Value::MUL:
348 return Bytecode::kMul; 482 return Bytecode::kMul;
349 case Token::Value::DIV: 483 case Token::Value::DIV:
350 return Bytecode::kDiv; 484 return Bytecode::kDiv;
351 case Token::Value::MOD: 485 case Token::Value::MOD:
352 return Bytecode::kMod; 486 return Bytecode::kMod;
353 default: 487 default:
354 UNIMPLEMENTED(); 488 UNIMPLEMENTED();
Michael Starzinger 2015/09/23 08:46:24 nit: This should actually be UNREACHABLE(), right?
oth 2015/09/23 10:46:56 Done.
355 return static_cast<Bytecode>(-1); 489 return static_cast<Bytecode>(-1);
356 } 490 }
357 } 491 }
358 492
359 493
360 // static 494 // static
361 bool BytecodeArrayBuilder::FitsInByteOperand(int value) { 495 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
496 switch (op) {
497 case Token::Value::EQ:
498 return Bytecode::kTestEqual;
499 case Token::Value::NE:
500 return Bytecode::kTestNotEqual;
501 case Token::Value::EQ_STRICT:
502 return Bytecode::kTestEqualStrict;
503 case Token::Value::NE_STRICT:
504 return Bytecode::kTestNotEqualStrict;
505 case Token::Value::LT:
506 return Bytecode::kTestLessThan;
507 case Token::Value::GT:
508 return Bytecode::kTestGreaterThan;
509 case Token::Value::LTE:
510 return Bytecode::kTestLessThanEqual;
511 case Token::Value::GTE:
512 return Bytecode::kTestGreaterThanEqual;
513 case Token::Value::INSTANCEOF:
514 return Bytecode::kTestInstanceOf;
515 case Token::Value::IN:
516 return Bytecode::kTestIn;
517 default:
518 UNIMPLEMENTED();
Michael Starzinger 2015/09/23 08:46:24 nit: This should actually be UNREACHABLE(), right?
oth 2015/09/23 10:46:56 Done.
519 return static_cast<Bytecode>(-1);
520 }
521 }
522
523
524 // static
525 bool BytecodeArrayBuilder::FitsInIdxOperand(int value) {
362 return 0 <= value && value <= 255; 526 return 0 <= value && value <= 255;
363 } 527 }
364 528
365 529
366 // static 530 // static
367 bool BytecodeArrayBuilder::FitsInByteOperand(size_t value) { 531 bool BytecodeArrayBuilder::FitsInIdxOperand(size_t value) {
368 return value <= 255; 532 return value <= 255;
369 } 533 }
370 534
371 535
536 // static
537 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) {
538 return -128 <= value && value < 128;
539 }
540
541
372 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) 542 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder)
373 : builder_(builder), count_(0), last_register_index_(-1) {} 543 : builder_(builder), count_(0), last_register_index_(-1) {}
374 544
375 545
376 TemporaryRegisterScope::~TemporaryRegisterScope() { 546 TemporaryRegisterScope::~TemporaryRegisterScope() {
377 while (count_-- != 0) { 547 while (count_-- != 0) {
378 builder_->ReturnTemporaryRegister(last_register_index_--); 548 builder_->ReturnTemporaryRegister(last_register_index_--);
379 } 549 }
380 } 550 }
381 551
382 552
383 Register TemporaryRegisterScope::NewRegister() { 553 Register TemporaryRegisterScope::NewRegister() {
384 count_++; 554 count_++;
385 last_register_index_ = builder_->BorrowTemporaryRegister(); 555 last_register_index_ = builder_->BorrowTemporaryRegister();
386 return Register(last_register_index_); 556 return Register(last_register_index_);
387 } 557 }
388 558
389 } // namespace interpreter 559 } // namespace interpreter
390 } // namespace internal 560 } // namespace internal
391 } // namespace v8 561 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698