bytecode-array-builder.cc 31.2 KB
Newer Older
1 2 3 4 5
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/interpreter/bytecode-array-builder.h"
6

7
#include "src/compiler.h"
yangguo's avatar
yangguo committed
8
#include "src/globals.h"
9
#include "src/interpreter/bytecode-array-writer.h"
10
#include "src/interpreter/bytecode-dead-code-optimizer.h"
11
#include "src/interpreter/bytecode-label.h"
12
#include "src/interpreter/bytecode-peephole-optimizer.h"
13
#include "src/interpreter/bytecode-register-optimizer.h"
14
#include "src/interpreter/interpreter-intrinsics.h"
15 16 17 18 19

namespace v8 {
namespace internal {
namespace interpreter {

20 21 22 23
BytecodeArrayBuilder::BytecodeArrayBuilder(
    Isolate* isolate, Zone* zone, int parameter_count, int context_count,
    int locals_count, FunctionLiteral* literal,
    SourcePositionTableBuilder::RecordingMode source_position_mode)
24
    : isolate_(isolate),
25
      zone_(zone),
26
      bytecode_generated_(false),
27
      constant_array_builder_(isolate, zone),
28
      handler_table_builder_(isolate, zone),
29
      return_seen_in_block_(false),
30 31 32
      parameter_count_(parameter_count),
      local_register_count_(locals_count),
      context_register_count_(context_count),
33
      temporary_allocator_(zone, fixed_register_count()),
34 35
      bytecode_array_writer_(isolate, zone, &constant_array_builder_,
                             source_position_mode),
36
      pipeline_(&bytecode_array_writer_) {
37 38
  DCHECK_GE(parameter_count_, 0);
  DCHECK_GE(context_register_count_, 0);
39
  DCHECK_GE(local_register_count_, 0);
40

41 42 43 44
  if (FLAG_ignition_deadcode) {
    pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_);
  }

45 46 47 48 49
  if (FLAG_ignition_peephole) {
    pipeline_ = new (zone)
        BytecodePeepholeOptimizer(&constant_array_builder_, pipeline_);
  }

50 51 52 53 54
  if (FLAG_ignition_reo) {
    pipeline_ = new (zone) BytecodeRegisterOptimizer(
        zone, &temporary_allocator_, parameter_count, pipeline_);
  }

55 56
  return_position_ =
      literal ? std::max(literal->start_position(), literal->end_position() - 1)
yangguo's avatar
yangguo committed
57
              : kNoSourcePosition;
58 59 60 61 62 63 64 65 66 67 68 69 70
}

Register BytecodeArrayBuilder::first_context_register() const {
  DCHECK_GT(context_register_count_, 0);
  return Register(local_register_count_);
}

Register BytecodeArrayBuilder::last_context_register() const {
  DCHECK_GT(context_register_count_, 0);
  return Register(local_register_count_ + context_register_count_ - 1);
}

Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
71
  DCHECK_GE(parameter_index, 0);
72
  return Register::FromParameterIndex(parameter_index, parameter_count());
73 74
}

75 76 77 78
bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const {
  return reg.is_parameter() || reg.index() < locals_count();
}

79
Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
80
  DCHECK(return_seen_in_block_);
81 82
  DCHECK(!bytecode_generated_);
  bytecode_generated_ = true;
83

84
  Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable();
85 86
  return pipeline_->ToBytecodeArray(fixed_register_count(), parameter_count(),
                                    handler_table);
87 88
}

89 90 91 92 93 94 95 96 97 98 99 100
namespace {

static bool ExpressionPositionIsNeeded(Bytecode bytecode) {
  // An expression position is always needed if filtering is turned
  // off. Otherwise an expression is only needed if the bytecode has
  // external side effects.
  return !FLAG_ignition_filter_expression_positions ||
         !Bytecodes::IsWithoutExternalSideEffects(bytecode);
}

}  // namespace

101 102
void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) {
  if (latest_source_info_.is_valid()) {
103 104 105 106 107 108
    // Statement positions need to be emitted immediately.  Expression
    // positions can be pushed back until a bytecode is found that can
    // throw. Hence we only invalidate the existing source position
    // information if it is used.
    if (latest_source_info_.is_statement() ||
        ExpressionPositionIsNeeded(node->bytecode())) {
109
      node->source_info().Clone(latest_source_info_);
110 111
      latest_source_info_.set_invalid();
    }
112 113 114
  }
}

115 116 117 118 119
void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
                                  uint32_t operand1, uint32_t operand2,
                                  uint32_t operand3) {
  DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3));
  BytecodeNode node(bytecode, operand0, operand1, operand2, operand3);
120 121
  AttachSourceInfo(&node);
  pipeline()->Write(&node);
122 123
}

124 125 126 127
void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
                                  uint32_t operand1, uint32_t operand2) {
  DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2));
  BytecodeNode node(bytecode, operand0, operand1, operand2);
128 129
  AttachSourceInfo(&node);
  pipeline()->Write(&node);
130
}
131

132 133 134 135
void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
                                  uint32_t operand1) {
  DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1));
  BytecodeNode node(bytecode, operand0, operand1);
136 137
  AttachSourceInfo(&node);
  pipeline()->Write(&node);
138 139
}

140 141 142
void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) {
  DCHECK(OperandsAreValid(bytecode, 1, operand0));
  BytecodeNode node(bytecode, operand0);
143 144
  AttachSourceInfo(&node);
  pipeline()->Write(&node);
145 146
}

147 148 149
void BytecodeArrayBuilder::Output(Bytecode bytecode) {
  DCHECK(OperandsAreValid(bytecode, 0));
  BytecodeNode node(bytecode);
150 151
  AttachSourceInfo(&node);
  pipeline()->Write(&node);
152 153 154
}

BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
155
                                                            Register reg) {
156
  Output(BytecodeForBinaryOperation(op), RegisterOperand(reg));
157 158 159
  return *this;
}

160
BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op) {
161 162 163 164
  Output(BytecodeForCountOperation(op));
  return *this;
}

165
BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
166
  Output(Bytecode::kToBooleanLogicalNot);
167 168 169 170 171 172 173 174 175
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
  Output(Bytecode::kTypeOf);
  return *this;
}

176 177
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
                                                             Register reg) {
178
  Output(BytecodeForCompareOperation(op), RegisterOperand(reg));
179 180 181
  return *this;
}

182 183 184 185 186 187
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
    size_t entry) {
  Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
  return *this;
}

188 189 190 191 192 193
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    v8::internal::Smi* smi) {
  int32_t raw_smi = smi->value();
  if (raw_smi == 0) {
    Output(Bytecode::kLdaZero);
  } else {
194
    Output(Bytecode::kLdaSmi, SignedOperand(raw_smi));
195 196 197 198 199 200
  }
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
  size_t entry = GetConstantPoolEntry(object);
201
  Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
  Output(Bytecode::kLdaUndefined);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
  Output(Bytecode::kLdaNull);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
  Output(Bytecode::kLdaTheHole);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
  Output(Bytecode::kLdaTrue);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
  Output(Bytecode::kLdaFalse);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
231
    Register reg) {
232
  Output(Bytecode::kLdar, RegisterOperand(reg));
233 234 235 236
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
237
    Register reg) {
238
  Output(Bytecode::kStar, RegisterOperand(reg));
239 240 241
  return *this;
}

242 243 244
BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
                                                         Register to) {
  DCHECK(from != to);
245
  Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to));
246 247 248
  return *this;
}

249 250
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot,
                                                       TypeofMode typeof_mode) {
251
  // TODO(rmcilroy): Potentially store typeof information in an
252
  // operand rather than having extra bytecodes.
253
  Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode);
254
  Output(bytecode, UnsignedOperand(feedback_slot));
255 256 257 258
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
259
    const Handle<String> name, int feedback_slot, LanguageMode language_mode) {
260
  Bytecode bytecode = BytecodeForStoreGlobal(language_mode);
261
  size_t name_index = GetConstantPoolEntry(name);
262
  Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
263 264 265
  return *this;
}

266 267
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
                                                            int slot_index) {
268 269
  Output(Bytecode::kLdaContextSlot, RegisterOperand(context),
         UnsignedOperand(slot_index));
270 271 272
  return *this;
}

273 274
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
                                                             int slot_index) {
275 276
  Output(Bytecode::kStaContextSlot, RegisterOperand(context),
         UnsignedOperand(slot_index));
277 278 279
  return *this;
}

280 281 282 283 284 285
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
    const Handle<String> name, TypeofMode typeof_mode) {
  Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF)
                          ? Bytecode::kLdaLookupSlotInsideTypeof
                          : Bytecode::kLdaLookupSlot;
  size_t name_index = GetConstantPoolEntry(name);
286
  Output(bytecode, UnsignedOperand(name_index));
287 288 289 290 291 292 293
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
    const Handle<String> name, LanguageMode language_mode) {
  Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode);
  size_t name_index = GetConstantPoolEntry(name);
294
  Output(bytecode, UnsignedOperand(name_index));
295 296 297
  return *this;
}

298
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
299
    Register object, const Handle<Name> name, int feedback_slot) {
300
  size_t name_index = GetConstantPoolEntry(name);
301 302
  Output(Bytecode::kLdaNamedProperty, RegisterOperand(object),
         UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
303 304 305 306
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
307
    Register object, int feedback_slot) {
308 309
  Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object),
         UnsignedOperand(feedback_slot));
310 311 312
  return *this;
}

313
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
314
    Register object, const Handle<Name> name, int feedback_slot,
315
    LanguageMode language_mode) {
316
  Bytecode bytecode = BytecodeForStoreNamedProperty(language_mode);
317
  size_t name_index = GetConstantPoolEntry(name);
318 319
  Output(bytecode, RegisterOperand(object), UnsignedOperand(name_index),
         UnsignedOperand(feedback_slot));
320 321 322 323 324 325
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
    Register object, Register key, int feedback_slot,
    LanguageMode language_mode) {
326
  Bytecode bytecode = BytecodeForStoreKeyedProperty(language_mode);
327 328
  Output(bytecode, RegisterOperand(object), RegisterOperand(key),
         UnsignedOperand(feedback_slot));
329 330 331
  return *this;
}

332 333
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry,
                                                          int flags) {
334
  Output(Bytecode::kCreateClosure, UnsignedOperand(entry),
335
         UnsignedOperand(flags));
336 337 338
  return *this;
}

339 340 341 342 343
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) {
  Output(Bytecode::kCreateFunctionContext, UnsignedOperand(slots));
  return *this;
}

344 345 346 347 348 349 350 351 352 353
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
    CreateArgumentsType type) {
  // TODO(rmcilroy): Consider passing the type as a bytecode operand rather
  // than having two different bytecodes once we have better support for
  // branches in the InterpreterAssembler.
  Bytecode bytecode = BytecodeForCreateArguments(type);
  Output(bytecode);
  return *this;
}

354
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
355 356
    Handle<String> pattern, int literal_index, int flags) {
  size_t pattern_entry = GetConstantPoolEntry(pattern);
357 358
  Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry),
         UnsignedOperand(literal_index), UnsignedOperand(flags));
359 360 361
  return *this;
}

362
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
363 364
    Handle<FixedArray> constant_elements, int literal_index, int flags) {
  size_t constant_elements_entry = GetConstantPoolEntry(constant_elements);
365 366 367
  Output(Bytecode::kCreateArrayLiteral,
         UnsignedOperand(constant_elements_entry),
         UnsignedOperand(literal_index), UnsignedOperand(flags));
368 369 370
  return *this;
}

371
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
372 373
    Handle<FixedArray> constant_properties, int literal_index, int flags) {
  size_t constant_properties_entry = GetConstantPoolEntry(constant_properties);
374 375 376
  Output(Bytecode::kCreateObjectLiteral,
         UnsignedOperand(constant_properties_entry),
         UnsignedOperand(literal_index), UnsignedOperand(flags));
377 378 379
  return *this;
}

380
BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
381
  Output(Bytecode::kPushContext, RegisterOperand(context));
382 383 384 385
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
386
  Output(Bytecode::kPopContext, RegisterOperand(context));
387 388 389
  return *this;
}

390 391 392
BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject(
    Register out) {
  Output(Bytecode::kToObject, RegisterOperand(out));
393 394 395
  return *this;
}

396 397 398
BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName(
    Register out) {
  Output(Bytecode::kToName, RegisterOperand(out));
399 400 401
  return *this;
}

402 403 404
BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber(
    Register out) {
  Output(Bytecode::kToNumber, RegisterOperand(out));
405 406 407
  return *this;
}

408
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
409
  pipeline_->BindLabel(label);
410
  LeaveBasicBlock();
411 412 413
  return *this;
}

414 415
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
                                                 BytecodeLabel* label) {
416
  pipeline_->BindLabel(target, label);
417
  LeaveBasicBlock();
418
  return *this;
419 420 421 422
}

BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode,
                                                       BytecodeLabel* label) {
423
  BytecodeNode node(jump_bytecode, 0);
424 425
  AttachSourceInfo(&node);
  pipeline_->WriteJump(&node, label);
426
  LeaveBasicBlock();
427 428 429 430 431 432 433 434
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
  return OutputJump(Bytecode::kJump, label);
}

BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
435 436 437
  // The peephole optimizer attempts to simplify JumpIfToBooleanTrue
  // to JumpIfTrue.
  return OutputJump(Bytecode::kJumpIfToBooleanTrue, label);
438 439 440
}

BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
441 442 443
  // The peephole optimizer attempts to simplify JumpIfToBooleanFalse
  // to JumpIfFalse.
  return OutputJump(Bytecode::kJumpIfToBooleanFalse, label);
444 445
}

446 447 448 449 450 451 452 453 454
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
  return OutputJump(Bytecode::kJumpIfNull, label);
}

BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
    BytecodeLabel* label) {
  return OutputJump(Bytecode::kJumpIfUndefined, label);
}

455 456 457 458 459
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
    BytecodeLabel* label) {
  return OutputJump(Bytecode::kJumpIfNotHole, label);
}

460
BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
yangguo's avatar
yangguo committed
461
  if (position != kNoSourcePosition) {
462 463 464 465 466 467 468 469 470 471 472
    // We need to attach a non-breakable source position to a stack
    // check, so we simply add it as expression position. There can be
    // a prior statement position from constructs like:
    //
    //    do var x;  while (false);
    //
    // A Nop could be inserted for empty statements, but since no code
    // is associated with these positions, instead we force the stack
    // check's expression position which eliminates the empty
    // statement's position.
    latest_source_info_.ForceExpressionPosition(position);
473
  }
474 475 476
  Output(Bytecode::kStackCheck);
  return *this;
}
477

478 479 480 481 482
BytecodeArrayBuilder& BytecodeArrayBuilder::OsrPoll(int loop_depth) {
  Output(Bytecode::kOsrPoll, UnsignedOperand(loop_depth));
  return *this;
}

483 484 485 486 487
BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
  Output(Bytecode::kThrow);
  return *this;
}

488 489 490 491 492
BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
  Output(Bytecode::kReThrow);
  return *this;
}

493
BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
494
  SetReturnPosition();
495
  Output(Bytecode::kReturn);
496
  return_seen_in_block_ = true;
497 498 499
  return *this;
}

500 501 502 503
BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
  Output(Bytecode::kDebugger);
  return *this;
}
504

505
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
506 507 508
    Register receiver, Register cache_info_triple) {
  Output(Bytecode::kForInPrepare, RegisterOperand(receiver),
         RegisterOperand(cache_info_triple));
509 510 511 512 513
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index,
                                                      Register cache_length) {
514 515
  Output(Bytecode::kForInDone, RegisterOperand(index),
         RegisterOperand(cache_length));
516 517 518
  return *this;
}

519
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
520 521
    Register receiver, Register index, Register cache_type_array_pair,
    int feedback_slot) {
522 523 524
  Output(Bytecode::kForInNext, RegisterOperand(receiver),
         RegisterOperand(index), RegisterOperand(cache_type_array_pair),
         UnsignedOperand(feedback_slot));
525 526 527
  return *this;
}

528
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
529
  Output(Bytecode::kForInStep, RegisterOperand(index));
530 531 532
  return *this;
}

533 534
BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
    Register generator) {
535
  Output(Bytecode::kSuspendGenerator, RegisterOperand(generator));
536 537 538 539 540
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
    Register generator) {
541
  Output(Bytecode::kResumeGenerator, RegisterOperand(generator));
542 543 544
  return *this;
}

545 546
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
    int handler_id, HandlerTable::CatchPrediction catch_prediction) {
547 548 549
  BytecodeLabel handler;
  Bind(&handler);
  handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
550
  handler_table_builder()->SetPrediction(handler_id, catch_prediction);
551 552 553 554 555
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
                                                         Register context) {
556 557 558
  BytecodeLabel try_begin;
  Bind(&try_begin);
  handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
559 560 561 562 563
  handler_table_builder()->SetContextRegister(handler_id, context);
  return *this;
}

BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
564 565 566
  BytecodeLabel try_end;
  Bind(&try_end);
  handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
567 568 569
  return *this;
}

570
void BytecodeArrayBuilder::EnsureReturn() {
571
  if (!return_seen_in_block_) {
572 573 574
    LoadUndefined();
    Return();
  }
575
  DCHECK(return_seen_in_block_);
576 577
}

578 579 580 581 582 583
BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
                                                 Register receiver_args,
                                                 size_t receiver_args_count,
                                                 int feedback_slot,
                                                 TailCallMode tail_call_mode) {
  Bytecode bytecode = BytecodeForCall(tail_call_mode);
584 585
  Output(bytecode, RegisterOperand(callable), RegisterOperand(receiver_args),
         UnsignedOperand(receiver_args_count), UnsignedOperand(feedback_slot));
586 587 588
  return *this;
}

589 590
BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
                                                Register first_arg,
591
                                                size_t arg_count) {
592
  if (!first_arg.is_valid()) {
593
    DCHECK_EQ(0u, arg_count);
594 595
    first_arg = Register(0);
  }
596
  Output(Bytecode::kNew, RegisterOperand(constructor),
597
         RegisterOperand(first_arg), UnsignedOperand(arg_count));
598 599 600
  return *this;
}

601 602
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
    Runtime::FunctionId function_id, Register first_arg, size_t arg_count) {
603
  DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
604
  DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
605
  if (!first_arg.is_valid()) {
606
    DCHECK_EQ(0u, arg_count);
607 608
    first_arg = Register(0);
  }
609 610 611 612 613 614 615 616 617 618
  Bytecode bytecode;
  uint32_t id;
  if (IntrinsicsHelper::IsSupported(function_id)) {
    bytecode = Bytecode::kInvokeIntrinsic;
    id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id));
  } else {
    bytecode = Bytecode::kCallRuntime;
    id = static_cast<uint32_t>(function_id);
  }
  Output(bytecode, id, RegisterOperand(first_arg), UnsignedOperand(arg_count));
619 620 621
  return *this;
}

622 623 624 625
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
    Runtime::FunctionId function_id, Register first_arg, size_t arg_count,
    Register first_return) {
  DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
626
  DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
627 628 629 630
  if (!first_arg.is_valid()) {
    DCHECK_EQ(0u, arg_count);
    first_arg = Register(0);
  }
631 632 633
  Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id),
         RegisterOperand(first_arg), UnsignedOperand(arg_count),
         RegisterOperand(first_return));
634 635 636
  return *this;
}

637 638
BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(
    int context_index, Register receiver_args, size_t receiver_args_count) {
639 640
  Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index),
         RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count));
641 642 643
  return *this;
}

644 645
BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
                                                   LanguageMode language_mode) {
646
  Output(BytecodeForDelete(language_mode), RegisterOperand(object));
647 648 649
  return *this;
}

650
size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
651
  return constant_array_builder()->Insert(object);
652 653
}

654 655 656 657 658 659 660 661 662
size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() {
  return constant_array_builder()->AllocateEntry();
}

void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry,
                                                     Handle<Object> object) {
  constant_array_builder()->InsertAllocatedEntry(entry, object);
}

663
void BytecodeArrayBuilder::SetReturnPosition() {
yangguo's avatar
yangguo committed
664
  if (return_position_ == kNoSourcePosition) return;
665
  latest_source_info_.MakeStatementPosition(return_position_);
666 667
}

668
void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) {
yangguo's avatar
yangguo committed
669
  if (stmt->position() == kNoSourcePosition) return;
670
  latest_source_info_.MakeStatementPosition(stmt->position());
671 672 673
}

void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) {
yangguo's avatar
yangguo committed
674
  if (expr->position() == kNoSourcePosition) return;
675
  if (!latest_source_info_.is_statement()) {
676 677
    // Ensure the current expression position is overwritten with the
    // latest value.
678
    latest_source_info_.MakeExpressionPosition(expr->position());
679
  }
680 681
}

682
void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) {
yangguo's avatar
yangguo committed
683
  if (expr->position() == kNoSourcePosition) return;
684
  latest_source_info_.MakeStatementPosition(expr->position());
685 686
}

687
bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
688
  return temporary_register_allocator()->RegisterIsLive(reg);
689 690
}

691
bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
692 693 694 695
  if (!reg.is_valid()) {
    return false;
  }

696
  if (reg.is_current_context() || reg.is_function_closure() ||
697 698 699
      reg.is_new_target()) {
    return true;
  } else if (reg.is_parameter()) {
700 701
    int parameter_index = reg.ToParameterIndex(parameter_count());
    return parameter_index >= 0 && parameter_index < parameter_count();
702 703
  } else if (reg.index() < fixed_register_count()) {
    return true;
704
  } else {
705
    return TemporaryRegisterIsLive(reg);
706 707 708
  }
}

709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
bool BytecodeArrayBuilder::OperandsAreValid(
    Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1,
    uint32_t operand2, uint32_t operand3) const {
  if (Bytecodes::NumberOfOperands(bytecode) != operand_count) {
    return false;
  }

  uint32_t operands[] = {operand0, operand1, operand2, operand3};
  const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
  for (int i = 0; i < operand_count; ++i) {
    switch (operand_types[i]) {
      case OperandType::kNone:
        return false;
      case OperandType::kRegCount: {
        CHECK_NE(i, 0);
        CHECK(operand_types[i - 1] == OperandType::kMaybeReg ||
              operand_types[i - 1] == OperandType::kReg);
726
        if (i > 0 && operands[i] > 0) {
727 728 729 730 731 732 733 734 735
          Register start = Register::FromOperand(operands[i - 1]);
          Register end(start.index() + static_cast<int>(operands[i]) - 1);
          if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) {
            return false;
          }
        }
        break;
      }
      case OperandType::kFlag8:
736
      case OperandType::kIntrinsicId:
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
        if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
            OperandSize::kByte) {
          return false;
        }
        break;
      case OperandType::kRuntimeId:
        if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
            OperandSize::kShort) {
          return false;
        }
        break;
      case OperandType::kIdx:
        // TODO(oth): Consider splitting OperandType::kIdx into two
        // operand types. One which is a constant pool index that can
        // be checked, and the other is an unsigned value.
        break;
      case OperandType::kImm:
        break;
      case OperandType::kMaybeReg:
        if (Register::FromOperand(operands[i]) == Register(0)) {
          break;
        }
      // Fall-through to kReg case.
      case OperandType::kReg:
      case OperandType::kRegOut: {
        Register reg = Register::FromOperand(operands[i]);
        if (!RegisterIsValid(reg)) {
          return false;
        }
        break;
      }
      case OperandType::kRegOutPair:
      case OperandType::kRegPair: {
        Register reg0 = Register::FromOperand(operands[i]);
        Register reg1 = Register(reg0.index() + 1);
        if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1)) {
          return false;
        }
        break;
      }
      case OperandType::kRegOutTriple: {
        Register reg0 = Register::FromOperand(operands[i]);
        Register reg1 = Register(reg0.index() + 1);
        Register reg2 = Register(reg0.index() + 2);
        if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1) ||
            !RegisterIsValid(reg2)) {
          return false;
        }
        break;
      }
    }
  }

  return true;
}

793 794 795 796 797 798 799 800 801 802 803
// static
Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
  switch (op) {
    case Token::Value::ADD:
      return Bytecode::kAdd;
    case Token::Value::SUB:
      return Bytecode::kSub;
    case Token::Value::MUL:
      return Bytecode::kMul;
    case Token::Value::DIV:
      return Bytecode::kDiv;
804 805
    case Token::Value::MOD:
      return Bytecode::kMod;
806 807 808 809 810 811
    case Token::Value::BIT_OR:
      return Bytecode::kBitwiseOr;
    case Token::Value::BIT_XOR:
      return Bytecode::kBitwiseXor;
    case Token::Value::BIT_AND:
      return Bytecode::kBitwiseAnd;
812 813 814 815 816 817
    case Token::Value::SHL:
      return Bytecode::kShiftLeft;
    case Token::Value::SAR:
      return Bytecode::kShiftRight;
    case Token::Value::SHR:
      return Bytecode::kShiftRightLogical;
818
    default:
819
      UNREACHABLE();
820
      return Bytecode::kIllegal;
821 822 823
  }
}

824 825 826 827 828 829 830 831 832
// static
Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) {
  switch (op) {
    case Token::Value::ADD:
      return Bytecode::kInc;
    case Token::Value::SUB:
      return Bytecode::kDec;
    default:
      UNREACHABLE();
833
      return Bytecode::kIllegal;
834 835 836
  }
}

837
// static
838 839 840 841 842 843 844 845 846 847 848 849 850
Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
  switch (op) {
    case Token::Value::EQ:
      return Bytecode::kTestEqual;
    case Token::Value::NE:
      return Bytecode::kTestNotEqual;
    case Token::Value::EQ_STRICT:
      return Bytecode::kTestEqualStrict;
    case Token::Value::LT:
      return Bytecode::kTestLessThan;
    case Token::Value::GT:
      return Bytecode::kTestGreaterThan;
    case Token::Value::LTE:
851
      return Bytecode::kTestLessThanOrEqual;
852
    case Token::Value::GTE:
853
      return Bytecode::kTestGreaterThanOrEqual;
854 855 856 857 858 859
    case Token::Value::INSTANCEOF:
      return Bytecode::kTestInstanceOf;
    case Token::Value::IN:
      return Bytecode::kTestIn;
    default:
      UNREACHABLE();
860
      return Bytecode::kIllegal;
861 862 863
  }
}

864
// static
865 866
Bytecode BytecodeArrayBuilder::BytecodeForStoreNamedProperty(
    LanguageMode language_mode) {
867 868
  switch (language_mode) {
    case SLOPPY:
869
      return Bytecode::kStaNamedPropertySloppy;
870
    case STRICT:
871
      return Bytecode::kStaNamedPropertyStrict;
872 873 874
    default:
      UNREACHABLE();
  }
875
  return Bytecode::kIllegal;
876 877 878
}

// static
879
Bytecode BytecodeArrayBuilder::BytecodeForStoreKeyedProperty(
880 881 882
    LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
883
      return Bytecode::kStaKeyedPropertySloppy;
884
    case STRICT:
885
      return Bytecode::kStaKeyedPropertyStrict;
886 887 888
    default:
      UNREACHABLE();
  }
889
  return Bytecode::kIllegal;
890 891
}

892
// static
893 894 895
Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(TypeofMode typeof_mode) {
  return typeof_mode == INSIDE_TYPEOF ? Bytecode::kLdaGlobalInsideTypeof
                                      : Bytecode::kLdaGlobal;
896 897 898 899 900 901 902 903 904 905 906 907 908
}

// static
Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal(
    LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kStaGlobalSloppy;
    case STRICT:
      return Bytecode::kStaGlobalStrict;
    default:
      UNREACHABLE();
  }
909
  return Bytecode::kIllegal;
910 911
}

912 913 914 915 916 917 918 919 920 921 922
// static
Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot(
    LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kStaLookupSlotSloppy;
    case STRICT:
      return Bytecode::kStaLookupSlotStrict;
    default:
      UNREACHABLE();
  }
923
  return Bytecode::kIllegal;
924 925
}

926 927 928 929 930 931 932 933
// static
Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments(
    CreateArgumentsType type) {
  switch (type) {
    case CreateArgumentsType::kMappedArguments:
      return Bytecode::kCreateMappedArguments;
    case CreateArgumentsType::kUnmappedArguments:
      return Bytecode::kCreateUnmappedArguments;
934 935
    case CreateArgumentsType::kRestParameter:
      return Bytecode::kCreateRestParameter;
936
  }
937
  UNREACHABLE();
938
  return Bytecode::kIllegal;
939 940 941 942 943 944 945 946 947 948 949 950
}

// static
Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kDeletePropertySloppy;
    case STRICT:
      return Bytecode::kDeletePropertyStrict;
    default:
      UNREACHABLE();
  }
951
  return Bytecode::kIllegal;
952 953
}

954 955 956 957 958 959 960 961 962 963
// static
Bytecode BytecodeArrayBuilder::BytecodeForCall(TailCallMode tail_call_mode) {
  switch (tail_call_mode) {
    case TailCallMode::kDisallow:
      return Bytecode::kCall;
    case TailCallMode::kAllow:
      return Bytecode::kTailCall;
    default:
      UNREACHABLE();
  }
964
  return Bytecode::kIllegal;
965
}
966

967 968 969
}  // namespace interpreter
}  // namespace internal
}  // namespace v8