1109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// found in the LICENSE file.
4109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
5109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/interpreter/interpreter-assembler.h"
6109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
7bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include <limits>
8109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include <ostream>
9109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
10109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/code-factory.h"
11109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/frames.h"
12109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/interface-descriptors.h"
13109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/interpreter/bytecodes.h"
14109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/interpreter/interpreter.h"
15109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/machine-type.h"
16109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/macro-assembler.h"
1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
18f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/zone/zone.h"
19109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
20109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochnamespace v8 {
21109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochnamespace internal {
22109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochnamespace interpreter {
23109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochusing compiler::CodeAssemblerState;
25109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochusing compiler::Node;
26109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochInterpreterAssembler::InterpreterAssembler(CodeAssemblerState* state,
283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                           Bytecode bytecode,
293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                           OperandScale operand_scale)
3062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    : CodeStubAssembler(state),
31109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      bytecode_(bytecode),
323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      operand_scale_(operand_scale),
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      bytecode_offset_(this, MachineType::PointerRepresentation()),
3413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      interpreted_frame_pointer_(this, MachineType::PointerRepresentation()),
3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      bytecode_array_(this, MachineRepresentation::kTagged),
3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      dispatch_table_(this, MachineType::PointerRepresentation()),
37109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      accumulator_(this, MachineRepresentation::kTagged),
383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      accumulator_use_(AccumulatorUse::kNone),
39bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      made_call_(false),
4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      reloaded_frame_ptr_(false),
4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      saved_bytecode_offset_(false),
42109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      disable_stack_check_across_call_(false),
43109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      stack_pointer_before_call_(nullptr) {
44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  accumulator_.Bind(Parameter(InterpreterDispatchDescriptor::kAccumulator));
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bytecode_offset_.Bind(
46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Parameter(InterpreterDispatchDescriptor::kBytecodeOffset));
4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bytecode_array_.Bind(
4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Parameter(InterpreterDispatchDescriptor::kBytecodeArray));
4962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  dispatch_table_.Bind(
5062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Parameter(InterpreterDispatchDescriptor::kDispatchTable));
5162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
52109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_trace_ignition) {
53109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry);
54109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
5562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  RegisterCallGenerationCallbacks([this] { CallPrologue(); },
5662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  [this] { CallEpilogue(); });
57109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
58109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochInterpreterAssembler::~InterpreterAssembler() {
603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If the following check fails the handler does not use the
613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // accumulator in the way described in the bytecode definitions in
623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // bytecodes.h.
633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_));
6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  UnregisterCallGenerationCallbacks();
653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
6713e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* InterpreterAssembler::GetInterpretedFramePointer() {
6813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (!interpreted_frame_pointer_.IsBound()) {
6913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    interpreted_frame_pointer_.Bind(LoadParentFramePointer());
7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             !reloaded_frame_ptr_) {
7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    interpreted_frame_pointer_.Bind(LoadParentFramePointer());
7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    reloaded_frame_ptr_ = true;
7413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
7513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return interpreted_frame_pointer_.value();
7613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
7713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::GetAccumulatorUnchecked() {
793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return accumulator_.value();
803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
81109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::GetAccumulator() {
833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(Bytecodes::ReadsAccumulator(bytecode_));
843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  accumulator_use_ = accumulator_use_ | AccumulatorUse::kRead;
853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return GetAccumulatorUnchecked();
863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
87109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
88109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::SetAccumulator(Node* value) {
893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(Bytecodes::WritesAccumulator(bytecode_));
903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  accumulator_use_ = accumulator_use_ | AccumulatorUse::kWrite;
91109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  accumulator_.Bind(value);
92109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
93109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
94bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* InterpreterAssembler::GetContext() {
95bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return LoadRegister(Register::current_context());
96bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
97109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
98109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::SetContext(Node* value) {
99109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  StoreRegister(value, Register::current_context());
100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
101109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* InterpreterAssembler::GetContextAtDepth(Node* context, Node* depth) {
103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable cur_context(this, MachineRepresentation::kTaggedPointer);
104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  cur_context.Bind(context);
105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
106f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable cur_depth(this, MachineRepresentation::kWord32);
107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  cur_depth.Bind(depth);
108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Label context_found(this);
110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context};
112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Label context_search(this, 2, context_search_loop_variables);
113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Fast path if the depth is 0.
115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(Word32Equal(depth, Int32Constant(0)), &context_found, &context_search);
116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Loop until the depth is 0.
118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Bind(&context_search);
119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
120f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    cur_depth.Bind(Int32Sub(cur_depth.value(), Int32Constant(1)));
121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    cur_context.Bind(
122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX));
123f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Branch(Word32Equal(cur_depth.value(), Int32Constant(0)), &context_found,
125c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch           &context_search);
126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
127f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Bind(&context_found);
129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return cur_context.value();
130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid InterpreterAssembler::GotoIfHasContextExtensionUpToDepth(Node* context,
133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                                              Node* depth,
134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                                              Label* target) {
135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable cur_context(this, MachineRepresentation::kTaggedPointer);
136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  cur_context.Bind(context);
137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable cur_depth(this, MachineRepresentation::kWord32);
139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  cur_depth.Bind(depth);
140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context};
142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Label context_search(this, 2, context_search_loop_variables);
143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Loop until the depth is 0.
145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Goto(&context_search);
146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Bind(&context_search);
147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // TODO(leszeks): We only need to do this check if the context had a sloppy
149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // eval, we could pass in a context chain bitmask to figure out which
150f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // contexts actually need to be checked.
151f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
152f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Node* extension_slot =
153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        LoadContextElement(cur_context.value(), Context::EXTENSION_INDEX);
154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
155f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Jump to the target if the extension slot is not a hole.
156f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    GotoIf(WordNotEqual(extension_slot, TheHoleConstant()), target);
157f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
158f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    cur_depth.Bind(Int32Sub(cur_depth.value(), Int32Constant(1)));
159f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    cur_context.Bind(
160c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX));
161f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
162f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    GotoIf(Word32NotEqual(cur_depth.value(), Int32Constant(0)),
163f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch           &context_search);
164f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
165f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
166f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
167109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::BytecodeOffset() {
16862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
16962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      (bytecode_offset_.value() ==
17062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       Parameter(InterpreterDispatchDescriptor::kBytecodeOffset))) {
17162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bytecode_offset_.Bind(LoadAndUntagRegister(Register::bytecode_offset()));
17262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return bytecode_offset_.value();
174109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
175109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
176109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::BytecodeArrayTaggedPointer() {
17762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Force a re-load of the bytecode array after every call in case the debugger
17862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // has been activated.
17962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (made_call_ &&
18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      (bytecode_array_.value() ==
18162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       Parameter(InterpreterDispatchDescriptor::kBytecodeArray))) {
18262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bytecode_array_.Bind(LoadRegister(Register::bytecode_array()));
183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
18462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return bytecode_array_.value();
185109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
186109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
187109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::DispatchTableRawPointer() {
18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      (dispatch_table_.value() ==
19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch       Parameter(InterpreterDispatchDescriptor::kDispatchTable))) {
19162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    dispatch_table_.Bind(ExternalConstant(
19262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        ExternalReference::interpreter_dispatch_table_address(isolate())));
19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return dispatch_table_.value();
195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
196109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
197109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::RegisterLocation(Node* reg_index) {
19813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IntPtrAdd(GetInterpretedFramePointer(),
19913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                   RegisterFrameOffset(reg_index));
200109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
201109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
202bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* InterpreterAssembler::RegisterFrameOffset(Node* index) {
203bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return WordShl(index, kPointerSizeLog2);
204109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
205109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
206109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::LoadRegister(Register reg) {
20713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return Load(MachineType::AnyTagged(), GetInterpretedFramePointer(),
208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              IntPtrConstant(reg.ToOperand() << kPointerSizeLog2));
209109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
210109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
211109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::LoadRegister(Node* reg_index) {
21213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return Load(MachineType::AnyTagged(), GetInterpretedFramePointer(),
213109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              RegisterFrameOffset(reg_index));
214109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
215109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
21662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::LoadAndUntagRegister(Register reg) {
21762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return LoadAndUntagSmi(GetInterpretedFramePointer(), reg.ToOperand()
21862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                           << kPointerSizeLog2);
21962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
22062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
221109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::StoreRegister(Node* value, Register reg) {
222bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return StoreNoWriteBarrier(
22313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      MachineRepresentation::kTagged, GetInterpretedFramePointer(),
224bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      IntPtrConstant(reg.ToOperand() << kPointerSizeLog2), value);
225109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
226109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
227109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
228109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return StoreNoWriteBarrier(MachineRepresentation::kTagged,
22913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                             GetInterpretedFramePointer(),
230109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                             RegisterFrameOffset(reg_index), value);
231109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
23362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::StoreAndTagRegister(compiler::Node* value,
23462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                Register reg) {
23562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int offset = reg.ToOperand() << kPointerSizeLog2;
23662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return StoreAndTagSmi(GetInterpretedFramePointer(), offset, value);
23762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
23862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::NextRegister(Node* reg_index) {
240109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Register indexes are negative, so the next index is minus one.
2413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return IntPtrAdd(reg_index, IntPtrConstant(-1));
2423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
2433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::OperandOffset(int operand_index) {
2453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return IntPtrConstant(
2463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()));
247109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
248109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandUnsignedByte(int operand_index) {
250109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
2513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize(
2523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    bytecode_, operand_index, operand_scale()));
2533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* operand_offset = OperandOffset(operand_index);
2543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(),
2553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              IntPtrAdd(BytecodeOffset(), operand_offset));
256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
257109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandSignedByte(int operand_index) {
259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
2603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize(
2613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    bytecode_, operand_index, operand_scale()));
2623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* operand_offset = OperandOffset(operand_index);
26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Load(MachineType::Int8(), BytecodeArrayTaggedPointer(),
26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              IntPtrAdd(BytecodeOffset(), operand_offset));
265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
266109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochcompiler::Node* InterpreterAssembler::BytecodeOperandReadUnaligned(
2683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int relative_offset, MachineType result_type) {
2693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  static const int kMaxCount = 4;
2703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(!TargetSupportsUnalignedAccess());
2713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int count;
2733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  switch (result_type.representation()) {
2743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case MachineRepresentation::kWord16:
2753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      count = 2;
2763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      break;
2773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case MachineRepresentation::kWord32:
2783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      count = 4;
2793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      break;
2803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    default:
2813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      UNREACHABLE();
2823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      break;
2833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
2843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  MachineType msb_type =
2853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      result_type.IsSigned() ? MachineType::Int8() : MachineType::Uint8();
2863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_TARGET_LITTLE_ENDIAN
2883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kStep = -1;
2893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int msb_offset = count - 1;
290109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#elif V8_TARGET_BIG_ENDIAN
2913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const int kStep = 1;
2923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int msb_offset = 0;
293109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else
294109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#error "Unknown Architecture"
295109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif
2963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Read the most signicant bytecode into bytes[0] and then in order
2983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // down to least significant in bytes[count - 1].
2993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(count <= kMaxCount);
3003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  compiler::Node* bytes[kMaxCount];
3013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  for (int i = 0; i < count; i++) {
3023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    MachineType machine_type = (i == 0) ? msb_type : MachineType::Uint8();
3033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Node* offset = IntPtrConstant(relative_offset + msb_offset + i * kStep);
3043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Node* array_offset = IntPtrAdd(BytecodeOffset(), offset);
3053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bytes[i] = Load(machine_type, BytecodeArrayTaggedPointer(), array_offset);
3063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Pack LSB to MSB.
3093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* result = bytes[--count];
3103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  for (int i = 1; --count >= 0; i++) {
3113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Node* shift = Int32Constant(i * kBitsPerByte);
3123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Node* value = Word32Shl(bytes[count], shift);
3133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    result = Word32Or(value, result);
314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return result;
316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandUnsignedShort(int operand_index) {
319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
3203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(
3213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      OperandSize::kShort,
3223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()));
3233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int operand_offset =
3243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
3253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (TargetSupportsUnalignedAccess()) {
3263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return Load(MachineType::Uint16(), BytecodeArrayTaggedPointer(),
3273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
3283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
3293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint16());
3303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
3323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandSignedShort(int operand_index) {
3343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
3353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(
3363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      OperandSize::kShort,
3373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()));
3383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int operand_offset =
3393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (TargetSupportsUnalignedAccess()) {
34162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Load(MachineType::Int16(), BytecodeArrayTaggedPointer(),
3423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
34462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return BytecodeOperandReadUnaligned(operand_offset, MachineType::Int16());
345109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandUnsignedQuad(int operand_index) {
3493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
3503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize(
3513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    bytecode_, operand_index, operand_scale()));
3523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int operand_offset =
3533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
3543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (TargetSupportsUnalignedAccess()) {
3553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return Load(MachineType::Uint32(), BytecodeArrayTaggedPointer(),
3563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
3573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
3583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint32());
3593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
3613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandSignedQuad(int operand_index) {
3633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
3643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize(
3653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    bytecode_, operand_index, operand_scale()));
3663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int operand_offset =
3673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
3683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (TargetSupportsUnalignedAccess()) {
36962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Load(MachineType::Int32(), BytecodeArrayTaggedPointer(),
3703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
3713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
37262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return BytecodeOperandReadUnaligned(operand_offset, MachineType::Int32());
3733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
3753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeSignedOperand(int operand_index,
3773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                  OperandSize operand_size) {
3783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(!Bytecodes::IsUnsignedOperandType(
3793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandType(bytecode_, operand_index)));
3803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  switch (operand_size) {
381109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case OperandSize::kByte:
3823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return BytecodeOperandSignedByte(operand_index);
383109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case OperandSize::kShort:
3843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return BytecodeOperandSignedShort(operand_index);
3853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case OperandSize::kQuad:
3863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return BytecodeOperandSignedQuad(operand_index);
387109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case OperandSize::kNone:
388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      UNREACHABLE();
389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return nullptr;
391109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeUnsignedOperand(int operand_index,
3943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                                    OperandSize operand_size) {
3953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(Bytecodes::IsUnsignedOperandType(
3963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandType(bytecode_, operand_index)));
3973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  switch (operand_size) {
398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case OperandSize::kByte:
3993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return BytecodeOperandUnsignedByte(operand_index);
400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case OperandSize::kShort:
4013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return BytecodeOperandUnsignedShort(operand_index);
4023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case OperandSize::kQuad:
4033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return BytecodeOperandUnsignedQuad(operand_index);
404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    case OperandSize::kNone:
405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      UNREACHABLE();
406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
407109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return nullptr;
408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
409109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
4103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandCount(int operand_index) {
4113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(OperandType::kRegCount,
4123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            Bytecodes::GetOperandType(bytecode_, operand_index));
4133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandSize operand_size =
4143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
4153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return BytecodeUnsignedOperand(operand_index, operand_size);
4163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
4173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandFlag(int operand_index) {
4193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(OperandType::kFlag8,
4203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            Bytecodes::GetOperandType(bytecode_, operand_index));
4213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandSize operand_size =
4223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
4233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(operand_size, OperandSize::kByte);
4243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return BytecodeUnsignedOperand(operand_index, operand_size);
4253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
4263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
427f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochNode* InterpreterAssembler::BytecodeOperandUImm(int operand_index) {
428f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK_EQ(OperandType::kUImm,
429f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            Bytecodes::GetOperandType(bytecode_, operand_index));
430f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  OperandSize operand_size =
431f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
432f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return BytecodeUnsignedOperand(operand_index, operand_size);
433f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
434f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
43562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::BytecodeOperandUImmWord(int operand_index) {
43662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeUint32ToWord(BytecodeOperandUImm(operand_index));
43762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
43862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
4393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandImm(int operand_index) {
4403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(OperandType::kImm,
4413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            Bytecodes::GetOperandType(bytecode_, operand_index));
4423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandSize operand_size =
4433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
4443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return BytecodeSignedOperand(operand_index, operand_size);
4453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
4463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
44762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::BytecodeOperandImmIntPtr(int operand_index) {
44862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeInt32ToIntPtr(BytecodeOperandImm(operand_index));
44962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
45062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
45162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::BytecodeOperandImmSmi(int operand_index) {
45262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return SmiFromWord32(BytecodeOperandImm(operand_index));
45362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
45462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
4553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandIdx(int operand_index) {
4563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(OperandType::kIdx ==
4573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Bytecodes::GetOperandType(bytecode_, operand_index));
4583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandSize operand_size =
4593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
46062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeUint32ToWord(
46162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      BytecodeUnsignedOperand(operand_index, operand_size));
46262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
46362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
46462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::BytecodeOperandIdxSmi(int operand_index) {
46562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return SmiTag(BytecodeOperandIdx(operand_index));
4663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
4673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
468109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::BytecodeOperandReg(int operand_index) {
4693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(Bytecodes::IsRegisterOperandType(
4703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandType(bytecode_, operand_index)));
4713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandSize operand_size =
4723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
47362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeInt32ToIntPtr(
47462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      BytecodeSignedOperand(operand_index, operand_size));
4753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
4763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* InterpreterAssembler::BytecodeOperandRuntimeId(int operand_index) {
4783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(OperandType::kRuntimeId ==
4793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Bytecodes::GetOperandType(bytecode_, operand_index));
4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  OperandSize operand_size =
4813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
4823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK_EQ(operand_size, OperandSize::kShort);
4833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return BytecodeUnsignedOperand(operand_index, operand_size);
484109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
48613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* InterpreterAssembler::BytecodeOperandIntrinsicId(int operand_index) {
48713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(OperandType::kIntrinsicId ==
48813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch         Bytecodes::GetOperandType(bytecode_, operand_index));
48913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  OperandSize operand_size =
49013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
49113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK_EQ(operand_size, OperandSize::kByte);
49213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return BytecodeUnsignedOperand(operand_index, operand_size);
49313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
49413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
495109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(),
497109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                        BytecodeArray::kConstantPoolOffset);
49862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return LoadFixedArrayElement(constant_pool, index);
499109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
501f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::LoadAndUntagConstantPoolEntry(Node* index) {
50262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return SmiUntag(LoadConstantPoolEntry(index));
503f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
50562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::LoadFeedbackVector() {
506bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* function = LoadRegister(Register::function_closure());
50762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* cell = LoadObjectField(function, JSFunction::kFeedbackVectorOffset);
50862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vector = LoadObjectField(cell, Cell::kValueOffset);
509109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return vector;
510109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
511109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
51262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid InterpreterAssembler::SaveBytecodeOffset() {
51362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
51462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  StoreAndTagRegister(BytecodeOffset(), Register::bytecode_offset());
51562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  saved_bytecode_offset_ = true;
51662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
51762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::CallPrologue() {
51962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!saved_bytecode_offset_) {
52062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // If there are multiple calls in the bytecode handler, you need to spill
52162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // before each of them, unless SaveBytecodeOffset has explicitly been called
52262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // in a path that dominates _all_ of those calls. Therefore don't set
52362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // saved_bytecode_offset_ to true or call SaveBytecodeOffset.
52462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    StoreAndTagRegister(BytecodeOffset(), Register::bytecode_offset());
52562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
526109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
527109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code && !disable_stack_check_across_call_) {
528109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(stack_pointer_before_call_ == nullptr);
529109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    stack_pointer_before_call_ = LoadStackPointer();
530109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
531bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  made_call_ = true;
532109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
534109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::CallEpilogue() {
535109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code && !disable_stack_check_across_call_) {
536109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Node* stack_pointer_after_call = LoadStackPointer();
537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Node* stack_pointer_before_call = stack_pointer_before_call_;
538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    stack_pointer_before_call_ = nullptr;
539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call,
540109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                        kUnexpectedStackPointer);
541109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
543109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
54462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::IncrementCallCount(Node* feedback_vector,
545f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                               Node* slot_id) {
546f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Comment("increment call count");
547f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
54862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* call_count = LoadFixedArrayElement(feedback_vector, call_count_slot);
54962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* new_count = SmiAdd(call_count, SmiConstant(1));
550f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Count is Smi, so we don't need a write barrier.
55162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return StoreFixedArrayElement(feedback_vector, call_count_slot, new_count,
55262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                SKIP_WRITE_BARRIER);
553f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
554f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                               Node* first_arg, Node* arg_count,
557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                               Node* slot_id,
55862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                               Node* feedback_vector,
559f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                               TailCallMode tail_call_mode) {
560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Static checks to assert it is safe to examine the type feedback element.
561f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // We don't know that we have a weak cell. We might have a private symbol
562f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // or an AllocationSite, but the memory is safe to examine.
563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
564f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // FixedArray.
565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
566f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
567f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // computed, meaning that it can't appear to be a pointer. If the low bit is
568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // 0, then hash is computed, but the 0 bit prevents the field from appearing
569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // to be a pointer.
57062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
57162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::IsCallOrConstruct(bytecode_));
572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    WeakCell::kValueOffset &&
575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                WeakCell::kValueOffset == Symbol::kHashFieldSlot);
576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Variable return_value(this, MachineRepresentation::kTagged);
578c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Label call_function(this), extra_checks(this, Label::kDeferred), call(this),
579c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      end(this);
580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
581f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // The checks. First, does function match the recorded monomorphic target?
58262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* feedback_element = LoadFixedArrayElement(feedback_vector, slot_id);
583c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element);
584f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* is_monomorphic = WordEqual(function, feedback_value);
58562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIfNot(is_monomorphic, &extra_checks);
586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
587c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // The compare above could have been a SMI/SMI comparison. Guard against
588c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // this convincing us that we have a monomorphic JSFunction.
589c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* is_smi = TaggedIsSmi(function);
590c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(is_smi, &extra_checks, &call_function);
591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Bind(&call_function);
593c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
594f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Increment the call count.
59562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    IncrementCallCount(feedback_vector, slot_id);
596f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Call using call function builtin.
598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Callable callable = CodeFactory::InterpreterPushArgsAndCall(
59962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), tail_call_mode, InterpreterPushArgsMode::kJSFunction);
600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* code_target = HeapConstant(callable.code());
601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* ret_value = CallStub(callable.descriptor(), code_target, context,
602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                               arg_count, first_arg, function);
603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return_value.Bind(ret_value);
604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Goto(&end);
605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
606f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bind(&extra_checks);
608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
609c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Label check_initialized(this), mark_megamorphic(this),
610c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        create_allocation_site(this);
611c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
612c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Comment("check if megamorphic");
613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Check if it is a megamorphic target.
61462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* is_megamorphic =
61562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        WordEqual(feedback_element,
61662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())));
617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GotoIf(is_megamorphic, &call);
618f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Comment("check if it is an allocation site");
62062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    GotoIfNot(IsAllocationSiteMap(LoadMap(feedback_element)),
62162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              &check_initialized);
622f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
623c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // If it is not the Array() function, mark megamorphic.
62462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* context_slot = LoadContextElement(LoadNativeContext(context),
62562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                            Context::ARRAY_FUNCTION_INDEX);
626c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* is_array_function = WordEqual(context_slot, function);
62762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    GotoIfNot(is_array_function, &mark_megamorphic);
628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
629c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // It is a monomorphic Array function. Increment the call count.
63062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    IncrementCallCount(feedback_vector, slot_id);
631c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
632c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Call ArrayConstructorStub.
633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Callable callable_call =
634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        CodeFactory::InterpreterPushArgsAndConstructArray(isolate());
635c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* code_target_call = HeapConstant(callable_call.code());
636c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* ret_value =
637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        CallStub(callable_call.descriptor(), code_target_call, context,
638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                 arg_count, function, feedback_element, first_arg);
639c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return_value.Bind(ret_value);
640c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Goto(&end);
641f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Bind(&check_initialized);
643f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Comment("check if uninitialized");
645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if it is uninitialized target first.
646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* is_uninitialized = WordEqual(
647f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          feedback_element,
64862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          HeapConstant(FeedbackVector::UninitializedSentinel(isolate())));
64962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GotoIfNot(is_uninitialized, &mark_megamorphic);
650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
651c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Comment("handle_unitinitialized");
652c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // If it is not a JSFunction mark it as megamorphic.
653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Node* is_smi = TaggedIsSmi(function);
654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      GotoIf(is_smi, &mark_megamorphic);
655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
656c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if function is an object of JSFunction type.
657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* instance_type = LoadInstanceType(function);
658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* is_js_function =
65962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE));
66062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GotoIfNot(is_js_function, &mark_megamorphic);
661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
662f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Check if it is the Array() function.
66362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* context_slot = LoadContextElement(LoadNativeContext(context),
66462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                              Context::ARRAY_FUNCTION_INDEX);
665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* is_array_function = WordEqual(context_slot, function);
666f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      GotoIf(is_array_function, &create_allocation_site);
667f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
668c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if the function belongs to the same native context.
669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* native_context = LoadNativeContext(
670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          LoadObjectField(function, JSFunction::kContextOffset));
671f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* is_same_native_context =
672f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          WordEqual(native_context, LoadNativeContext(context));
67362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GotoIfNot(is_same_native_context, &mark_megamorphic);
674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
67562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CreateWeakCellInFeedbackVector(feedback_vector, SmiTag(slot_id),
676f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                     function);
677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Call using call function builtin.
679f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Goto(&call_function);
680f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
681f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
682f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Bind(&create_allocation_site);
683f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    {
68462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CreateAllocationSiteInFeedbackVector(feedback_vector, SmiTag(slot_id));
685f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
686f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Call using CallFunction builtin. CallICs have a PREMONOMORPHIC state.
687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // They start collecting feedback only when a call is executed the second
688f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // time. So, do not pass any feedback here.
689f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Goto(&call_function);
690f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Bind(&mark_megamorphic);
693f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
694f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Mark it as a megamorphic.
695f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // MegamorphicSentinel is created as a part of Heap::InitialObjects
696f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // and will not move during a GC. So it is safe to skip write barrier.
697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
698f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      StoreFixedArrayElement(
69962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          feedback_vector, slot_id,
70062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())),
701f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          SKIP_WRITE_BARRIER);
702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Goto(&call);
703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
704f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
705f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
706f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bind(&call);
707f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
708c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Comment("Increment call count and call using Call builtin");
709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Increment the call count.
71062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    IncrementCallCount(feedback_vector, slot_id);
711f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
712f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Call using call builtin.
713f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
71462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), tail_call_mode, InterpreterPushArgsMode::kOther);
715f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Node* code_target_call = HeapConstant(callable_call.code());
716f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Node* ret_value = CallStub(callable_call.descriptor(), code_target_call,
717f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                               context, arg_count, first_arg, function);
718f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return_value.Bind(ret_value);
719f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Goto(&end);
720f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
721f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bind(&end);
723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return return_value.value();
724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
726109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::CallJS(Node* function, Node* context,
727109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                   Node* first_arg, Node* arg_count,
728109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                   TailCallMode tail_call_mode) {
72962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
73062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::IsCallOrConstruct(bytecode_));
731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Callable callable = CodeFactory::InterpreterPushArgsAndCall(
73262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), tail_call_mode, InterpreterPushArgsMode::kOther);
733109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* code_target = HeapConstant(callable.code());
73462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
735109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return CallStub(callable.descriptor(), code_target, context, arg_count,
736109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                  first_arg, function);
737109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
738109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
73962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::CallJSWithSpread(Node* function, Node* context,
74062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                             Node* first_arg, Node* arg_count) {
74162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
74262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Callable callable = CodeFactory::InterpreterPushArgsAndCall(
74362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), TailCallMode::kDisallow,
74462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      InterpreterPushArgsMode::kWithFinalSpread);
74562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* code_target = HeapConstant(callable.code());
74662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
74762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return CallStub(callable.descriptor(), code_target, context, arg_count,
74862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  first_arg, function);
74962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
75062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
75162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::Construct(Node* constructor, Node* context,
75262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                      Node* new_target, Node* first_arg,
75362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                      Node* arg_count, Node* slot_id,
75462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                      Node* feedback_vector) {
75562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
756f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable return_value(this, MachineRepresentation::kTagged);
757f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Variable allocation_feedback(this, MachineRepresentation::kTagged);
758c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Label call_construct_function(this, &allocation_feedback),
759c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      extra_checks(this, Label::kDeferred), call_construct(this), end(this);
760f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
761f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Slot id of 0 is used to indicate no type feedback is available.
76262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0);
76362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* is_feedback_unavailable = WordEqual(slot_id, IntPtrConstant(0));
764f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GotoIf(is_feedback_unavailable, &call_construct);
765f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
766f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check that the constructor is not a smi.
767c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* is_smi = TaggedIsSmi(constructor);
768f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GotoIf(is_smi, &call_construct);
769f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
770f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check that constructor is a JSFunction.
771f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* instance_type = LoadInstanceType(constructor);
772f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* is_js_function =
77362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE));
77462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIfNot(is_js_function, &call_construct);
775f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
776c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Check if it is a monomorphic constructor.
77762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* feedback_element = LoadFixedArrayElement(feedback_vector, slot_id);
778c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element);
779c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* is_monomorphic = WordEqual(constructor, feedback_value);
780c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  allocation_feedback.Bind(UndefinedConstant());
781c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(is_monomorphic, &call_construct_function, &extra_checks);
782c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
783c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Bind(&call_construct_function);
784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
78562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Comment("call using ConstructFunction");
78662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    IncrementCallCount(feedback_vector, slot_id);
787c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct(
78862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), InterpreterPushArgsMode::kJSFunction);
789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return_value.Bind(CallStub(callable_function.descriptor(),
790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               HeapConstant(callable_function.code()), context,
791c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               arg_count, new_target, constructor,
792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               allocation_feedback.value(), first_arg));
793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Goto(&end);
794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
795c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
796c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Bind(&extra_checks);
797f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Label check_allocation_site(this), check_initialized(this),
799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        initialize(this), mark_megamorphic(this);
800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Check if it is a megamorphic target.
802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Comment("check if megamorphic");
80362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* is_megamorphic =
80462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        WordEqual(feedback_element,
80562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())));
806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GotoIf(is_megamorphic, &call_construct_function);
807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Comment("check if weak cell");
809c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* is_weak_cell = WordEqual(LoadMap(feedback_element),
810c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   LoadRoot(Heap::kWeakCellMapRootIndex));
81162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    GotoIfNot(is_weak_cell, &check_allocation_site);
812c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
813c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // If the weak cell is cleared, we have a new chance to become
814c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // monomorphic.
815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Comment("check if weak cell is cleared");
816c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* is_smi = TaggedIsSmi(feedback_value);
817c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Branch(is_smi, &initialize, &mark_megamorphic);
818c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
819c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Bind(&check_allocation_site);
820f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    {
821c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Comment("check if it is an allocation site");
822c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Node* is_allocation_site =
823c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          WordEqual(LoadObjectField(feedback_element, 0),
824c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                    LoadRoot(Heap::kAllocationSiteMapRootIndex));
82562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GotoIfNot(is_allocation_site, &check_initialized);
826f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
827c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Make sure the function is the Array() function.
82862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* context_slot = LoadContextElement(LoadNativeContext(context),
82962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                              Context::ARRAY_FUNCTION_INDEX);
830c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Node* is_array_function = WordEqual(context_slot, constructor);
83162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GotoIfNot(is_array_function, &mark_megamorphic);
832f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      allocation_feedback.Bind(feedback_element);
834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Goto(&call_construct_function);
835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
836f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Bind(&check_initialized);
838c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
839c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if it is uninitialized.
840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Comment("check if uninitialized");
841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Node* is_uninitialized = WordEqual(
842c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex));
843c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Branch(is_uninitialized, &initialize, &mark_megamorphic);
844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
845f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
846c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Bind(&initialize);
847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Label create_allocation_site(this), create_weak_cell(this);
849c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Comment("initialize the feedback element");
850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Create an allocation site if the function is an array function,
851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // otherwise create a weak cell.
85262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* context_slot = LoadContextElement(LoadNativeContext(context),
85362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                              Context::ARRAY_FUNCTION_INDEX);
854c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Node* is_array_function = WordEqual(context_slot, constructor);
855c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Branch(is_array_function, &create_allocation_site, &create_weak_cell);
856f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
857c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Bind(&create_allocation_site);
858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
85962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* site = CreateAllocationSiteInFeedbackVector(feedback_vector,
860c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                                          SmiTag(slot_id));
861c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        allocation_feedback.Bind(site);
862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Goto(&call_construct_function);
863f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
864f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
865c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Bind(&create_weak_cell);
866f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      {
86762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CreateWeakCellInFeedbackVector(feedback_vector, SmiTag(slot_id),
868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                       constructor);
869f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Goto(&call_construct_function);
870f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
871f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
872f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
873c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Bind(&mark_megamorphic);
874f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    {
875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // MegamorphicSentinel is an immortal immovable object so
876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // write-barrier is not needed.
877c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Comment("transition to megamorphic");
878c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
879c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      StoreFixedArrayElement(
88062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          feedback_vector, slot_id,
88162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())),
882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          SKIP_WRITE_BARRIER);
883c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Goto(&call_construct_function);
884f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
885f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
886f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
887f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Bind(&call_construct);
888f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
88962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Comment("call using Construct builtin");
890f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(
89162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), InterpreterPushArgsMode::kOther);
892f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Node* code_target = HeapConstant(callable.code());
893f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return_value.Bind(CallStub(callable.descriptor(), code_target, context,
894f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                               arg_count, new_target, constructor,
895f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                               UndefinedConstant(), first_arg));
896f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Goto(&end);
897f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
898f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
899f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Bind(&end);
900f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return return_value.value();
901109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
902109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
90362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::ConstructWithSpread(Node* constructor,
90462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                Node* context, Node* new_target,
90562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                Node* first_arg,
90662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                Node* arg_count) {
90762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
90862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable return_value(this, MachineRepresentation::kTagged);
90962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Comment("call using ConstructWithSpread");
91062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(
91162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), InterpreterPushArgsMode::kWithFinalSpread);
91262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* code_target = HeapConstant(callable.code());
91362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return_value.Bind(CallStub(callable.descriptor(), code_target, context,
91462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             arg_count, new_target, constructor,
91562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             UndefinedConstant(), first_arg));
91662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
91762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return return_value.value();
91862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
91962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context,
921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                         Node* first_arg, Node* arg_count,
922109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                         int result_size) {
92362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
92462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::IsCallRuntime(bytecode_));
925109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size);
926109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* code_target = HeapConstant(callable.code());
927109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
928109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Get the function entry from the function id.
929109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* function_table = ExternalConstant(
930109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      ExternalReference::runtime_function_table_address(isolate()));
931109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* function_offset =
932109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Int32Mul(function_id, Int32Constant(sizeof(Runtime::Function)));
93362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* function =
93462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      IntPtrAdd(function_table, ChangeUint32ToWord(function_offset));
935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* function_entry =
936109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Load(MachineType::Pointer(), function,
9373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch           IntPtrConstant(offsetof(Runtime::Function, entry)));
938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
93962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return CallStubR(callable.descriptor(), result_size, code_target, context,
94062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   arg_count, first_arg, function_entry);
941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
942109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
94362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid InterpreterAssembler::UpdateInterruptBudget(Node* weight, bool backward) {
944bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label ok(this), interrupt_check(this, Label::kDeferred), end(this);
945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* budget_offset =
946109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag);
947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Update budget by |weight| and check if it reaches zero.
949bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Variable new_budget(this, MachineRepresentation::kWord32);
950109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* old_budget =
951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset);
95262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (backward) {
95362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    new_budget.Bind(Int32Sub(old_budget, weight));
95462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
95562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    new_budget.Bind(Int32Add(old_budget, weight));
95662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
957bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* condition =
958bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0));
959109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Branch(condition, &ok, &interrupt_check);
960109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
961109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Perform interrupt and reset budget.
962109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Bind(&interrupt_check);
963bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  {
964bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    CallRuntime(Runtime::kInterrupt, GetContext());
965bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    new_budget.Bind(Int32Constant(Interpreter::InterruptBudget()));
966bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Goto(&ok);
967bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
968109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
969109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Update budget.
970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Bind(&ok);
971109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  StoreNoWriteBarrier(MachineRepresentation::kWord32,
972bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                      BytecodeArrayTaggedPointer(), budget_offset,
973bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                      new_budget.value());
974109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
975109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
976f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::Advance() {
977f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return Advance(Bytecodes::Size(bytecode_, operand_scale_));
978f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
979f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
980109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochNode* InterpreterAssembler::Advance(int delta) {
981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return Advance(IntPtrConstant(delta));
982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
98462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::Advance(Node* delta, bool backward) {
985f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (FLAG_trace_ignition) {
986f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    TraceBytecode(Runtime::kInterpreterTraceBytecodeExit);
987f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
98862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* next_offset = backward ? IntPtrSub(BytecodeOffset(), delta)
98962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               : IntPtrAdd(BytecodeOffset(), delta);
990f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bytecode_offset_.Bind(next_offset);
991f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return next_offset;
992109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
993109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
99462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::Jump(Node* delta, bool backward) {
995f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!Bytecodes::IsStarLookahead(bytecode_, operand_scale_));
996f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
99762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  UpdateInterruptBudget(TruncateWordToWord32(delta), backward);
99862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* new_bytecode_offset = Advance(delta, backward);
999f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* target_bytecode = LoadBytecode(new_bytecode_offset);
1000f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return DispatchToBytecode(target_bytecode, new_bytecode_offset);
1001109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1002109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
100362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::Jump(Node* delta) { return Jump(delta, false); }
100462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
100562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* InterpreterAssembler::JumpBackward(Node* delta) {
100662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Jump(delta, true);
100762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
100862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1009109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::JumpConditional(Node* condition, Node* delta) {
1010bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label match(this), no_match(this);
1011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1012c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(condition, &match, &no_match);
1013109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Bind(&match);
1014109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Jump(delta);
1015109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Bind(&no_match);
1016109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Dispatch();
1017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1018109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) {
1020109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  JumpConditional(WordEqual(lhs, rhs), delta);
1021109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1022109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1023109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs,
1024109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                              Node* delta) {
1025109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  JumpConditional(WordNotEqual(lhs, rhs), delta);
1026109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1027109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1028f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::LoadBytecode(compiler::Node* bytecode_offset) {
1029f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* bytecode =
1030f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), bytecode_offset);
103162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeUint32ToWord(bytecode);
1032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1033109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1034f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::StarDispatchLookahead(Node* target_bytecode) {
1035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Label do_inline_star(this), done(this);
1036f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1037c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Variable var_bytecode(this, MachineType::PointerRepresentation());
1038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  var_bytecode.Bind(target_bytecode);
1039f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1040f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* star_bytecode = IntPtrConstant(static_cast<int>(Bytecode::kStar));
1041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* is_star = WordEqual(target_bytecode, star_bytecode);
1042c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(is_star, &do_inline_star, &done);
1043f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1044f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bind(&do_inline_star);
1045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
1046f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    InlineStar();
1047f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    var_bytecode.Bind(LoadBytecode(BytecodeOffset()));
1048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Goto(&done);
10493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bind(&done);
1051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return var_bytecode.value();
1052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid InterpreterAssembler::InlineStar() {
1055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bytecode previous_bytecode = bytecode_;
1056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  AccumulatorUse previous_acc_use = accumulator_use_;
1057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bytecode_ = Bytecode::kStar;
1059f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  accumulator_use_ = AccumulatorUse::kNone;
1060f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (FLAG_trace_ignition) {
1062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry);
1063f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1064f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  StoreRegister(GetAccumulator(), BytecodeOperandReg(0));
1065f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_));
1067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Advance();
1069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bytecode_ = previous_bytecode;
1070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  accumulator_use_ = previous_acc_use;
1071f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::Dispatch() {
107462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Comment("========= Dispatch");
107562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_IMPLIES(Bytecodes::MakesCallAlongCriticalPath(bytecode_), made_call_);
1076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* target_offset = Advance();
1077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* target_bytecode = LoadBytecode(target_offset);
1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (Bytecodes::IsStarLookahead(bytecode_, operand_scale_)) {
1080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    target_bytecode = StarDispatchLookahead(target_bytecode);
1081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return DispatchToBytecode(target_bytecode, BytecodeOffset());
1083f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::DispatchToBytecode(Node* target_bytecode,
1086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                               Node* new_bytecode_offset) {
1087bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (FLAG_trace_ignition_dispatches) {
1088bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    TraceBytecodeDispatch(target_bytecode);
1089bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1090bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1091bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* target_code_entry =
1092109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Load(MachineType::Pointer(), DispatchTableRawPointer(),
10933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch           WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2)));
1094109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1095bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset);
1096bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1097bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* InterpreterAssembler::DispatchToBytecodeHandler(Node* handler,
1099bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                                      Node* bytecode_offset) {
110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(ishell): Add CSA::CodeEntryPoint(code).
1101bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* handler_entry =
110262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      IntPtrAdd(BitcastTaggedToWord(handler),
110362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                IntPtrConstant(Code::kHeaderSize - kHeapObjectTag));
1104bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return DispatchToBytecodeHandlerEntry(handler_entry, bytecode_offset);
1105109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1106109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1107bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* InterpreterAssembler::DispatchToBytecodeHandlerEntry(
1108bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* handler_entry, Node* bytecode_offset) {
1109109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  InterpreterDispatchDescriptor descriptor(isolate());
111062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return TailCallBytecodeDispatch(
111162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      descriptor, handler_entry, GetAccumulatorUnchecked(), bytecode_offset,
111262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      BytecodeArrayTaggedPointer(), DispatchTableRawPointer());
1113109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1114109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
11153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid InterpreterAssembler::DispatchWide(OperandScale operand_scale) {
11163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Dispatching a wide bytecode requires treating the prefix
11173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // bytecode a base pointer into the dispatch table and dispatching
11183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the bytecode that follows relative to this base.
11193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  //
11203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  //   Indices 0-255 correspond to bytecodes with operand_scale == 0
11213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  //   Indices 256-511 correspond to bytecodes with operand_scale == 1
11223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  //   Indices 512-767 correspond to bytecodes with operand_scale == 2
112362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_IMPLIES(Bytecodes::MakesCallAlongCriticalPath(bytecode_), made_call_);
11243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* next_bytecode_offset = Advance(1);
1125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* next_bytecode = LoadBytecode(next_bytecode_offset);
1126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (FLAG_trace_ignition_dispatches) {
1128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    TraceBytecodeDispatch(next_bytecode);
1129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
11313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* base_index;
11323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  switch (operand_scale) {
11333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case OperandScale::kDouble:
11343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      base_index = IntPtrConstant(1 << kBitsPerByte);
11353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      break;
11363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case OperandScale::kQuadruple:
11373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      base_index = IntPtrConstant(2 << kBitsPerByte);
11383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      break;
11393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    default:
11403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      UNREACHABLE();
11413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      base_index = nullptr;
11423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
11433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* target_index = IntPtrAdd(base_index, next_bytecode);
1144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* target_code_entry =
11453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Load(MachineType::Pointer(), DispatchTableRawPointer(),
11463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch           WordShl(target_index, kPointerSizeLog2));
11473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1148bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DispatchToBytecodeHandlerEntry(target_code_entry, next_bytecode_offset);
11493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
11503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::TruncateTaggedToWord32WithFeedback(
1152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* context, Node* value, Variable* var_type_feedback) {
1153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // We might need to loop once due to ToNumber conversion.
1154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Variable var_value(this, MachineRepresentation::kTagged),
1155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      var_result(this, MachineRepresentation::kWord32);
1156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Variable* loop_vars[] = {&var_value, var_type_feedback};
1157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Label loop(this, 2, loop_vars), done_loop(this, &var_result);
1158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  var_value.Bind(value);
115962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNone));
1160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Goto(&loop);
1161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bind(&loop);
1162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
1163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Load the current {value}.
1164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    value = var_value.value();
1165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Check if the {value} is a Smi or a HeapObject.
1167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Label if_valueissmi(this), if_valueisnotsmi(this);
1168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
1169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Bind(&if_valueissmi);
1171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
1172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Convert the Smi {value}.
1173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      var_result.Bind(SmiToWord32(value));
1174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      var_type_feedback->Bind(
117562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          SmiOr(var_type_feedback->value(),
117662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                SmiConstant(BinaryOperationFeedback::kSignedSmall)));
1177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Goto(&done_loop);
1178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Bind(&if_valueisnotsmi);
1181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
1182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Check if {value} is a HeapNumber.
1183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Label if_valueisheapnumber(this),
1184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          if_valueisnotheapnumber(this, Label::kDeferred);
1185c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Node* value_map = LoadMap(value);
118662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(IsHeapNumberMap(value_map), &if_valueisheapnumber,
118762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             &if_valueisnotheapnumber);
1188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Bind(&if_valueisheapnumber);
1190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      {
1191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // Truncate the floating point value.
1192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        var_result.Bind(TruncateHeapNumberValueToWord32(value));
1193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        var_type_feedback->Bind(
119462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            SmiOr(var_type_feedback->value(),
119562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  SmiConstant(BinaryOperationFeedback::kNumber)));
1196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Goto(&done_loop);
1197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
1198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Bind(&if_valueisnotheapnumber);
1200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      {
1201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // We do not require an Or with earlier feedback here because once we
1202c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // convert the value to a number, we cannot reach this path. We can
1203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // only reach this path on the first pass when the feedback is kNone.
120462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CSA_ASSERT(this, SmiEqual(var_type_feedback->value(),
120562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  SmiConstant(BinaryOperationFeedback::kNone)));
1206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Label if_valueisoddball(this),
1208c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            if_valueisnotoddball(this, Label::kDeferred);
1209c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Node* is_oddball = Word32Equal(LoadMapInstanceType(value_map),
1210c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                       Int32Constant(ODDBALL_TYPE));
1211c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Branch(is_oddball, &if_valueisoddball, &if_valueisnotoddball);
1212c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1213c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Bind(&if_valueisoddball);
1214c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert Oddball to a Number and perform checks again.
1216c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          var_value.Bind(LoadObjectField(value, Oddball::kToNumberOffset));
1217c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          var_type_feedback->Bind(
121862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
1219c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          Goto(&loop);
1220c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1221c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1222c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Bind(&if_valueisnotoddball);
1223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1224c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert the {value} to a Number first.
1225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          Callable callable = CodeFactory::NonNumberToNumber(isolate());
1226c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          var_value.Bind(CallStub(callable, context, value));
122762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kAny));
1228c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          Goto(&loop);
1229c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
1231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bind(&done_loop);
1234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return var_result.value();
1235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1237bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InterpreterAssembler::UpdateInterruptBudgetOnReturn() {
1238109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // TODO(rmcilroy): Investigate whether it is worth supporting self
1239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // optimization of primitive functions like FullCodegen.
1240109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1241109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Update profiling count by -BytecodeOffset to simulate backedge to start of
1242109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // function.
1243109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* profiling_weight =
1244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize),
124562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               TruncateWordToWord32(BytecodeOffset()));
124662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  UpdateInterruptBudget(profiling_weight, false);
1247109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1248109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1249bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* InterpreterAssembler::StackCheckTriggeredInterrupt() {
1250109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* sp = LoadStackPointer();
1251109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* stack_limit = Load(
1252109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      MachineType::Pointer(),
1253109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      ExternalConstant(ExternalReference::address_of_stack_limit(isolate())));
1254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return UintPtrLessThan(sp, stack_limit);
1255109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* InterpreterAssembler::LoadOSRNestingLevel() {
125862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return LoadObjectField(BytecodeArrayTaggedPointer(),
125962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                         BytecodeArray::kOSRNestingLevelOffset,
126062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                         MachineType::Int8());
1261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1263109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::Abort(BailoutReason bailout_reason) {
1264109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  disable_stack_check_across_call_ = true;
1265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Node* abort_id = SmiTag(Int32Constant(bailout_reason));
12663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  CallRuntime(Runtime::kAbort, GetContext(), abort_id);
1267109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  disable_stack_check_across_call_ = false;
1268109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1269109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1270109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs,
1271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                               BailoutReason bailout_reason) {
1272bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label ok(this), abort(this, Label::kDeferred);
1273c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(WordEqual(lhs, rhs), &ok, &abort);
1274109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Bind(&abort);
1276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Abort(bailout_reason);
1277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Goto(&ok);
1278bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1279bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Bind(&ok);
1280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
128262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid InterpreterAssembler::MaybeDropFrames(Node* context) {
128362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* restart_fp_address =
128462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ExternalConstant(ExternalReference::debug_restart_fp_address(isolate()));
128562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
128662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* restart_fp = Load(MachineType::Pointer(), restart_fp_address);
128762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* null = IntPtrConstant(0);
128862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
128962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label ok(this), drop_frames(this);
129062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Branch(IntPtrEqual(restart_fp, null), &ok, &drop_frames);
129162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
129262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&drop_frames);
129362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // We don't expect this call to return since the frame dropper tears down
129462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // the stack and jumps into the function on the target frame to restart it.
129562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallStub(CodeFactory::FrameDropperTrampoline(isolate()), context, restart_fp);
129662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Abort(kUnexpectedReturnFromFrameDropper);
129762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Goto(&ok);
129862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
129962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&ok);
130062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
130162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) {
1303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntime(function_id, GetContext(), BytecodeArrayTaggedPointer(),
13043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              SmiTag(BytecodeOffset()), GetAccumulatorUnchecked());
1305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1307bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid InterpreterAssembler::TraceBytecodeDispatch(Node* target_bytecode) {
1308bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* counters_table = ExternalConstant(
1309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      ExternalReference::interpreter_dispatch_counters(isolate()));
1310bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* source_bytecode_table_index = IntPtrConstant(
1311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      static_cast<int>(bytecode_) * (static_cast<int>(Bytecode::kLast) + 1));
1312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1313bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* counter_offset =
1314bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      WordShl(IntPtrAdd(source_bytecode_table_index, target_bytecode),
1315bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              IntPtrConstant(kPointerSizeLog2));
1316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* old_counter =
1317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Load(MachineType::IntPtr(), counters_table, counter_offset);
1318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1319bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label counter_ok(this), counter_saturated(this, Label::kDeferred);
1320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1321bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* counter_reached_max = WordEqual(
1322bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      old_counter, IntPtrConstant(std::numeric_limits<uintptr_t>::max()));
1323c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Branch(counter_reached_max, &counter_saturated, &counter_ok);
1324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Bind(&counter_ok);
1326bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  {
1327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* new_counter = IntPtrAdd(old_counter, IntPtrConstant(1));
1328bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    StoreNoWriteBarrier(MachineType::PointerRepresentation(), counters_table,
1329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                        counter_offset, new_counter);
1330bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Goto(&counter_saturated);
1331bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1332bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1333bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Bind(&counter_saturated);
1334bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1335bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// static
1337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochbool InterpreterAssembler::TargetSupportsUnalignedAccess() {
1338109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
1339109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return false;
13403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87 || \
1341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || \
1342f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    V8_TARGET_ARCH_PPC
1343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return true;
1344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else
1345109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#error "Unknown Architecture"
1346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif
1347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
1348109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* InterpreterAssembler::RegisterCount() {
1350bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* bytecode_array = LoadRegister(Register::bytecode_array());
1351bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* frame_size = LoadObjectField(
135262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Uint32());
135362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return WordShr(ChangeUint32ToWord(frame_size),
135462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 IntPtrConstant(kPointerSizeLog2));
1355bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1356bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1357bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* InterpreterAssembler::ExportRegisterFile(Node* array) {
135862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* register_count = RegisterCount();
1359bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (FLAG_debug_code) {
1360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* array_size = LoadAndUntagFixedArrayBaseLength(array);
136162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    AbortIfWordNotEqual(array_size, register_count,
136262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        kInvalidRegisterFileInGenerator);
1363bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1364bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
136562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_index(this, MachineType::PointerRepresentation());
136662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  var_index.Bind(IntPtrConstant(0));
1367bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1368bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Iterate over register file and write values into array.
1369bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // The mapping of register to array index must match that used in
1370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // BytecodeGraphBuilder::VisitResumeGenerator.
1371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label loop(this, &var_index), done_loop(this);
1372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Goto(&loop);
1373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Bind(&loop);
1374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  {
1375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* index = var_index.value();
137662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    GotoIfNot(UintPtrLessThan(index, register_count), &done_loop);
1377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
137862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index);
137962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value = LoadRegister(reg_index);
1380bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1381bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    StoreFixedArrayElement(array, index, value);
1382bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
138362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    var_index.Bind(IntPtrAdd(index, IntPtrConstant(1)));
1384bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Goto(&loop);
1385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1386bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Bind(&done_loop);
1387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return array;
1389bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* InterpreterAssembler::ImportRegisterFile(Node* array) {
139262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* register_count = RegisterCount();
1393bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (FLAG_debug_code) {
1394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* array_size = LoadAndUntagFixedArrayBaseLength(array);
139562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    AbortIfWordNotEqual(array_size, register_count,
139662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        kInvalidRegisterFileInGenerator);
1397bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1398bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
139962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_index(this, MachineType::PointerRepresentation());
140062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  var_index.Bind(IntPtrConstant(0));
1401bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1402bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Iterate over array and write values into register file.  Also erase the
1403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // array contents to not keep them alive artificially.
1404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Label loop(this, &var_index), done_loop(this);
1405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Goto(&loop);
1406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Bind(&loop);
1407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  {
1408bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* index = var_index.value();
140962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    GotoIfNot(UintPtrLessThan(index, register_count), &done_loop);
1410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1411bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* value = LoadFixedArrayElement(array, index);
1412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
141362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index);
141462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    StoreRegister(value, reg_index);
1415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    StoreFixedArrayElement(array, index, StaleRegisterConstant());
1417bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
141862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    var_index.Bind(IntPtrAdd(index, IntPtrConstant(1)));
1419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Goto(&loop);
1420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1421bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Bind(&done_loop);
1422bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1423bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return array;
1424bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1425bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1426109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}  // namespace interpreter
1427109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}  // namespace internal
1428109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}  // namespace v8
1429