84279bfcca
Remove OffThreadHandle, HandleOrOffThreadHandle, and HandleFor, and make the OffThreadIsolate allocate "real" Handles. Rather than using the main-thread Isolate's handle scopes, these off-thread Handles are backed by a Zone, which is tied to the lifetime of the nearest OffThreadHandleScope. Eventually, we'll likely want to merge the implementation of OffThreadHandleScope and HandleScope, but currently the latter is too tightly coupled to the main thread to do so. Bug: chromium:1011762 Change-Id: I2a6361931fe3f90a7bef4cc28ee42155fa8d062f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2071865 Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#66516}
656 lines
29 KiB
C++
656 lines
29 KiB
C++
// Copyright 2015 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
|
|
#define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
|
|
|
|
#include "src/ast/ast.h"
|
|
#include "src/base/compiler-specific.h"
|
|
#include "src/base/export-template.h"
|
|
#include "src/common/globals.h"
|
|
#include "src/interpreter/bytecode-array-writer.h"
|
|
#include "src/interpreter/bytecode-flags.h"
|
|
#include "src/interpreter/bytecode-register-allocator.h"
|
|
#include "src/interpreter/bytecode-register.h"
|
|
#include "src/interpreter/bytecode-source-info.h"
|
|
#include "src/interpreter/bytecodes.h"
|
|
#include "src/interpreter/constant-array-builder.h"
|
|
#include "src/interpreter/handler-table-builder.h"
|
|
#include "src/zone/zone-containers.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
class BytecodeArray;
|
|
class FeedbackVectorSpec;
|
|
class Isolate;
|
|
|
|
namespace interpreter {
|
|
|
|
class BytecodeLabel;
|
|
class BytecodeLoopHeader;
|
|
class BytecodeNode;
|
|
class BytecodeRegisterOptimizer;
|
|
class BytecodeJumpTable;
|
|
class Register;
|
|
|
|
class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
|
|
public:
|
|
BytecodeArrayBuilder(
|
|
Zone* zone, int parameter_count, int locals_count,
|
|
FeedbackVectorSpec* feedback_vector_spec = nullptr,
|
|
SourcePositionTableBuilder::RecordingMode source_position_mode =
|
|
SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS);
|
|
|
|
template <typename LocalIsolate>
|
|
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
|
|
Handle<BytecodeArray> ToBytecodeArray(LocalIsolate* isolate);
|
|
template <typename LocalIsolate>
|
|
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
|
|
Handle<ByteArray> ToSourcePositionTable(LocalIsolate* isolate);
|
|
|
|
#ifdef DEBUG
|
|
int CheckBytecodeMatches(BytecodeArray bytecode);
|
|
#endif
|
|
|
|
// Get the number of parameters expected by function.
|
|
int parameter_count() const {
|
|
DCHECK_GE(parameter_count_, 0);
|
|
return parameter_count_;
|
|
}
|
|
|
|
// Get the number of locals required for bytecode array.
|
|
int locals_count() const {
|
|
DCHECK_GE(local_register_count_, 0);
|
|
return local_register_count_;
|
|
}
|
|
|
|
// Returns the number of fixed (non-temporary) registers.
|
|
int fixed_register_count() const { return locals_count(); }
|
|
|
|
// Returns the number of fixed and temporary registers.
|
|
int total_register_count() const {
|
|
DCHECK_LE(fixed_register_count(),
|
|
register_allocator()->maximum_register_count());
|
|
return register_allocator()->maximum_register_count();
|
|
}
|
|
|
|
Register Local(int index) const;
|
|
Register Parameter(int parameter_index) const;
|
|
Register Receiver() const;
|
|
|
|
// Constant loads to accumulator.
|
|
BytecodeArrayBuilder& LoadConstantPoolEntry(size_t entry);
|
|
BytecodeArrayBuilder& LoadLiteral(Smi value);
|
|
BytecodeArrayBuilder& LoadLiteral(double value);
|
|
BytecodeArrayBuilder& LoadLiteral(const AstRawString* raw_string);
|
|
BytecodeArrayBuilder& LoadLiteral(const Scope* scope);
|
|
BytecodeArrayBuilder& LoadLiteral(AstBigInt bigint);
|
|
BytecodeArrayBuilder& LoadLiteral(AstSymbol symbol);
|
|
BytecodeArrayBuilder& LoadUndefined();
|
|
BytecodeArrayBuilder& LoadNull();
|
|
BytecodeArrayBuilder& LoadTheHole();
|
|
BytecodeArrayBuilder& LoadTrue();
|
|
BytecodeArrayBuilder& LoadFalse();
|
|
BytecodeArrayBuilder& LoadBoolean(bool value);
|
|
|
|
// Global loads to the accumulator and stores from the accumulator.
|
|
BytecodeArrayBuilder& LoadGlobal(const AstRawString* name, int feedback_slot,
|
|
TypeofMode typeof_mode);
|
|
BytecodeArrayBuilder& StoreGlobal(const AstRawString* name,
|
|
int feedback_slot);
|
|
|
|
// Load the object at |slot_index| at |depth| in the context chain starting
|
|
// with |context| into the accumulator.
|
|
enum ContextSlotMutability { kImmutableSlot, kMutableSlot };
|
|
BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index,
|
|
int depth,
|
|
ContextSlotMutability immutable);
|
|
|
|
// Stores the object in the accumulator into |slot_index| at |depth| in the
|
|
// context chain starting with |context|.
|
|
BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index,
|
|
int depth);
|
|
|
|
// Load from a module variable into the accumulator. |depth| is the depth of
|
|
// the current context relative to the module context.
|
|
BytecodeArrayBuilder& LoadModuleVariable(int cell_index, int depth);
|
|
|
|
// Store from the accumulator into a module variable. |depth| is the depth of
|
|
// the current context relative to the module context.
|
|
BytecodeArrayBuilder& StoreModuleVariable(int cell_index, int depth);
|
|
|
|
// Register-accumulator transfers.
|
|
BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
|
|
BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
|
|
|
|
// Register-register transfer.
|
|
BytecodeArrayBuilder& MoveRegister(Register from, Register to);
|
|
|
|
// Named load property.
|
|
BytecodeArrayBuilder& LoadNamedProperty(Register object,
|
|
const AstRawString* name,
|
|
int feedback_slot);
|
|
// Named load property without feedback
|
|
BytecodeArrayBuilder& LoadNamedPropertyNoFeedback(Register object,
|
|
const AstRawString* name);
|
|
|
|
// Keyed load property. The key should be in the accumulator.
|
|
BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
|
|
|
|
// Named load property of the @@iterator symbol.
|
|
BytecodeArrayBuilder& LoadIteratorProperty(Register object,
|
|
int feedback_slot);
|
|
|
|
// Load and call property of the @@iterator symbol
|
|
BytecodeArrayBuilder& GetIterator(Register object, int load_feedback_slot,
|
|
int call_feedback_slot);
|
|
|
|
// Named load property of the @@asyncIterator symbol.
|
|
BytecodeArrayBuilder& LoadAsyncIteratorProperty(Register object,
|
|
int feedback_slot);
|
|
|
|
// Store properties. Flag for NeedsSetFunctionName() should
|
|
// be in the accumulator.
|
|
BytecodeArrayBuilder& StoreDataPropertyInLiteral(
|
|
Register object, Register name, DataPropertyInLiteralFlags flags,
|
|
int feedback_slot);
|
|
|
|
// Collect type information for developer tools. The value for which we
|
|
// record the type is stored in the accumulator.
|
|
BytecodeArrayBuilder& CollectTypeProfile(int position);
|
|
|
|
// Store a property named by a property name. The value to be stored should be
|
|
// in the accumulator.
|
|
BytecodeArrayBuilder& StoreNamedProperty(Register object,
|
|
const AstRawString* name,
|
|
int feedback_slot,
|
|
LanguageMode language_mode);
|
|
|
|
// Store a property named by a property name without feedback slot. The value
|
|
// to be stored should be in the accumulator.
|
|
BytecodeArrayBuilder& StoreNamedPropertyNoFeedback(
|
|
Register object, const AstRawString* name, LanguageMode language_mode);
|
|
|
|
// Store a property named by a constant from the constant pool. The value to
|
|
// be stored should be in the accumulator.
|
|
BytecodeArrayBuilder& StoreNamedProperty(Register object,
|
|
size_t constant_pool_entry,
|
|
int feedback_slot,
|
|
LanguageMode language_mode);
|
|
// Store an own property named by a constant from the constant pool. The
|
|
// value to be stored should be in the accumulator.
|
|
BytecodeArrayBuilder& StoreNamedOwnProperty(Register object,
|
|
const AstRawString* name,
|
|
int feedback_slot);
|
|
// Store a property keyed by a value in a register. The value to be stored
|
|
// should be in the accumulator.
|
|
BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
|
|
int feedback_slot,
|
|
LanguageMode language_mode);
|
|
// Store an own element in an array literal. The value to be stored should be
|
|
// in the accumulator.
|
|
BytecodeArrayBuilder& StoreInArrayLiteral(Register array, Register index,
|
|
int feedback_slot);
|
|
// Store the home object property. The value to be stored should be in the
|
|
// accumulator.
|
|
BytecodeArrayBuilder& StoreHomeObjectProperty(Register object,
|
|
int feedback_slot,
|
|
LanguageMode language_mode);
|
|
|
|
// Store the class fields property. The initializer to be stored should
|
|
// be in the accumulator.
|
|
BytecodeArrayBuilder& StoreClassFieldsInitializer(Register constructor,
|
|
int feedback_slot);
|
|
|
|
// Load class fields property.
|
|
BytecodeArrayBuilder& LoadClassFieldsInitializer(Register constructor,
|
|
int feedback_slot);
|
|
|
|
// Lookup the variable with |name|.
|
|
BytecodeArrayBuilder& LoadLookupSlot(const AstRawString* name,
|
|
TypeofMode typeof_mode);
|
|
|
|
// Lookup the variable with |name|, which is known to be at |slot_index| at
|
|
// |depth| in the context chain if not shadowed by a context extension
|
|
// somewhere in that context chain.
|
|
BytecodeArrayBuilder& LoadLookupContextSlot(const AstRawString* name,
|
|
TypeofMode typeof_mode,
|
|
int slot_index, int depth);
|
|
|
|
// Lookup the variable with |name|, which has its feedback in |feedback_slot|
|
|
// and is known to be global if not shadowed by a context extension somewhere
|
|
// up to |depth| in that context chain.
|
|
BytecodeArrayBuilder& LoadLookupGlobalSlot(const AstRawString* name,
|
|
TypeofMode typeof_mode,
|
|
int feedback_slot, int depth);
|
|
|
|
// Store value in the accumulator into the variable with |name|.
|
|
BytecodeArrayBuilder& StoreLookupSlot(
|
|
const AstRawString* name, LanguageMode language_mode,
|
|
LookupHoistingMode lookup_hoisting_mode);
|
|
|
|
// Create a new closure for a SharedFunctionInfo which will be inserted at
|
|
// constant pool index |shared_function_info_entry|.
|
|
BytecodeArrayBuilder& CreateClosure(size_t shared_function_info_entry,
|
|
int slot, int flags);
|
|
|
|
// Create a new local context for a |scope|.
|
|
BytecodeArrayBuilder& CreateBlockContext(const Scope* scope);
|
|
|
|
// Create a new context for a catch block with |exception| and |scope|.
|
|
BytecodeArrayBuilder& CreateCatchContext(Register exception,
|
|
const Scope* scope);
|
|
|
|
// Create a new context with the given |scope| and size |slots|.
|
|
BytecodeArrayBuilder& CreateFunctionContext(const Scope* scope, int slots);
|
|
|
|
// Create a new eval context with the given |scope| and size |slots|.
|
|
BytecodeArrayBuilder& CreateEvalContext(const Scope* scope, int slots);
|
|
|
|
// Creates a new context with the given |scope| for a with-statement
|
|
// with the |object| in a register.
|
|
BytecodeArrayBuilder& CreateWithContext(Register object, const Scope* scope);
|
|
|
|
// Create a new arguments object in the accumulator.
|
|
BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
|
|
|
|
// Literals creation. Constant elements should be in the accumulator.
|
|
BytecodeArrayBuilder& CreateRegExpLiteral(const AstRawString* pattern,
|
|
int literal_index, int flags);
|
|
BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
|
|
int literal_index, int flags);
|
|
BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
|
|
BytecodeArrayBuilder& CreateArrayFromIterable();
|
|
BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
|
|
int literal_index, int flags);
|
|
BytecodeArrayBuilder& CreateEmptyObjectLiteral();
|
|
BytecodeArrayBuilder& CloneObject(Register source, int flags,
|
|
int feedback_slot);
|
|
|
|
// Gets or creates the template for a TemplateObjectDescription which will
|
|
// be inserted at constant pool index |template_object_description_entry|.
|
|
BytecodeArrayBuilder& GetTemplateObject(
|
|
size_t template_object_description_entry, int feedback_slot);
|
|
|
|
// Push the context in accumulator as the new context, and store in register
|
|
// |context|.
|
|
BytecodeArrayBuilder& PushContext(Register context);
|
|
|
|
// Pop the current context and replace with |context|.
|
|
BytecodeArrayBuilder& PopContext(Register context);
|
|
|
|
// Call a JS function which is known to be a property of a JS object. The
|
|
// JSFunction or Callable to be called should be in |callable|. The arguments
|
|
// should be in |args|, with the receiver in |args[0]|. The call type of the
|
|
// expression is in |call_type|. Type feedback is recorded in the
|
|
// |feedback_slot| in the type feedback vector.
|
|
BytecodeArrayBuilder& CallProperty(Register callable, RegisterList args,
|
|
int feedback_slot);
|
|
|
|
// Call a JS function with an known undefined receiver. The JSFunction or
|
|
// Callable to be called should be in |callable|. The arguments should be in
|
|
// |args|, with no receiver as it is implicitly set to undefined. Type
|
|
// feedback is recorded in the |feedback_slot| in the type feedback vector.
|
|
BytecodeArrayBuilder& CallUndefinedReceiver(Register callable,
|
|
RegisterList args,
|
|
int feedback_slot);
|
|
|
|
// Call a JS function with an any receiver, possibly (but not necessarily)
|
|
// undefined. The JSFunction or Callable to be called should be in |callable|.
|
|
// The arguments should be in |args|, with the receiver in |args[0]|. Type
|
|
// feedback is recorded in the |feedback_slot| in the type feedback vector.
|
|
BytecodeArrayBuilder& CallAnyReceiver(Register callable, RegisterList args,
|
|
int feedback_slot);
|
|
|
|
// Call a JS function with an any receiver, possibly (but not necessarily)
|
|
// undefined. The JSFunction or Callable to be called should be in |callable|.
|
|
// The arguments should be in |args|, with the receiver in |args[0]|.
|
|
BytecodeArrayBuilder& CallNoFeedback(Register callable, RegisterList args);
|
|
|
|
// Tail call into a JS function. The JSFunction or Callable to be called
|
|
// should be in |callable|. The arguments should be in |args|, with the
|
|
// receiver in |args[0]|. Type feedback is recorded in the |feedback_slot| in
|
|
// the type feedback vector.
|
|
BytecodeArrayBuilder& TailCall(Register callable, RegisterList args,
|
|
int feedback_slot);
|
|
|
|
// Call a JS function. The JSFunction or Callable to be called should be in
|
|
// |callable|, the receiver in |args[0]| and the arguments in |args[1]|
|
|
// onwards. The final argument must be a spread.
|
|
BytecodeArrayBuilder& CallWithSpread(Register callable, RegisterList args,
|
|
int feedback_slot);
|
|
|
|
// Call the Construct operator. The accumulator holds the |new_target|.
|
|
// The |constructor| is in a register and arguments are in |args|.
|
|
BytecodeArrayBuilder& Construct(Register constructor, RegisterList args,
|
|
int feedback_slot);
|
|
|
|
// Call the Construct operator for use with a spread. The accumulator holds
|
|
// the |new_target|. The |constructor| is in a register and arguments are in
|
|
// |args|. The final argument must be a spread.
|
|
BytecodeArrayBuilder& ConstructWithSpread(Register constructor,
|
|
RegisterList args,
|
|
int feedback_slot);
|
|
|
|
// Call the runtime function with |function_id| and arguments |args|.
|
|
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
|
|
RegisterList args);
|
|
// Call the runtime function with |function_id| with single argument |arg|.
|
|
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
|
|
Register arg);
|
|
// Call the runtime function with |function_id| with no arguments.
|
|
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id);
|
|
|
|
// Call the runtime function with |function_id| and arguments |args|, that
|
|
// returns a pair of values. The return values will be returned in
|
|
// |return_pair|.
|
|
BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
|
|
RegisterList args,
|
|
RegisterList return_pair);
|
|
// Call the runtime function with |function_id| with single argument |arg|
|
|
// that returns a pair of values. The return values will be returned in
|
|
// |return_pair|.
|
|
BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
|
|
Register arg,
|
|
RegisterList return_pair);
|
|
|
|
// Call the JS runtime function with |context_index| and arguments |args|,
|
|
// with no receiver as it is implicitly set to undefined.
|
|
BytecodeArrayBuilder& CallJSRuntime(int context_index, RegisterList args);
|
|
|
|
// Operators (register holds the lhs value, accumulator holds the rhs value).
|
|
// Type feedback will be recorded in the |feedback_slot|
|
|
BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
|
|
int feedback_slot);
|
|
// Same as above, but lhs in the accumulator and rhs in |literal|.
|
|
BytecodeArrayBuilder& BinaryOperationSmiLiteral(Token::Value binop,
|
|
Smi literal,
|
|
int feedback_slot);
|
|
|
|
// Unary and Count Operators (value stored in accumulator).
|
|
// Type feedback will be recorded in the |feedback_slot|
|
|
BytecodeArrayBuilder& UnaryOperation(Token::Value op, int feedback_slot);
|
|
|
|
enum class ToBooleanMode {
|
|
kConvertToBoolean, // Perform ToBoolean conversion on accumulator.
|
|
kAlreadyBoolean, // Accumulator is already a Boolean.
|
|
};
|
|
|
|
// Unary Operators.
|
|
BytecodeArrayBuilder& LogicalNot(ToBooleanMode mode);
|
|
BytecodeArrayBuilder& TypeOf();
|
|
|
|
// Expects a heap object in the accumulator. Returns its super constructor in
|
|
// the register |out| if it passes the IsConstructor test. Otherwise, it
|
|
// throws a TypeError exception.
|
|
BytecodeArrayBuilder& GetSuperConstructor(Register out);
|
|
|
|
// Deletes property from an object. This expects that accumulator contains
|
|
// the key to be deleted and the register contains a reference to the object.
|
|
BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
|
|
|
|
// JavaScript defines two kinds of 'nil'.
|
|
enum NilValue { kNullValue, kUndefinedValue };
|
|
|
|
// Tests.
|
|
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
|
|
int feedback_slot);
|
|
BytecodeArrayBuilder& CompareReference(Register reg);
|
|
BytecodeArrayBuilder& CompareUndetectable();
|
|
BytecodeArrayBuilder& CompareUndefined();
|
|
BytecodeArrayBuilder& CompareNull();
|
|
BytecodeArrayBuilder& CompareNil(Token::Value op, NilValue nil);
|
|
BytecodeArrayBuilder& CompareTypeOf(
|
|
TestTypeOfFlags::LiteralFlag literal_flag);
|
|
|
|
// Converts accumulator and stores result in register |out|.
|
|
BytecodeArrayBuilder& ToObject(Register out);
|
|
BytecodeArrayBuilder& ToName(Register out);
|
|
BytecodeArrayBuilder& ToString();
|
|
|
|
// Converts accumulator and stores result back in accumulator.
|
|
BytecodeArrayBuilder& ToNumber(int feedback_slot);
|
|
BytecodeArrayBuilder& ToNumeric(int feedback_slot);
|
|
|
|
// Exception handling.
|
|
BytecodeArrayBuilder& MarkHandler(int handler_id,
|
|
HandlerTable::CatchPrediction will_catch);
|
|
BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
|
|
BytecodeArrayBuilder& MarkTryEnd(int handler_id);
|
|
|
|
// Flow Control.
|
|
BytecodeArrayBuilder& Bind(BytecodeLabel* label);
|
|
BytecodeArrayBuilder& Bind(BytecodeLoopHeader* label);
|
|
BytecodeArrayBuilder& Bind(BytecodeJumpTable* jump_table, int case_value);
|
|
|
|
BytecodeArrayBuilder& Jump(BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpLoop(BytecodeLoopHeader* loop_header,
|
|
int loop_depth);
|
|
|
|
BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpIfNotNull(BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpIfUndefinedOrNull(BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpIfNotUndefined(BytecodeLabel* label);
|
|
BytecodeArrayBuilder& JumpIfNil(BytecodeLabel* label, Token::Value op,
|
|
NilValue nil);
|
|
BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op,
|
|
NilValue nil);
|
|
|
|
BytecodeArrayBuilder& SwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
|
|
|
|
BytecodeArrayBuilder& StackCheck(int position);
|
|
|
|
// Sets the pending message to the value in the accumulator, and returns the
|
|
// previous pending message in the accumulator.
|
|
BytecodeArrayBuilder& SetPendingMessage();
|
|
|
|
BytecodeArrayBuilder& Throw();
|
|
BytecodeArrayBuilder& ReThrow();
|
|
BytecodeArrayBuilder& Abort(AbortReason reason);
|
|
BytecodeArrayBuilder& Return();
|
|
BytecodeArrayBuilder& ThrowReferenceErrorIfHole(const AstRawString* name);
|
|
BytecodeArrayBuilder& ThrowSuperNotCalledIfHole();
|
|
BytecodeArrayBuilder& ThrowSuperAlreadyCalledIfNotHole();
|
|
|
|
// Debugger.
|
|
BytecodeArrayBuilder& Debugger();
|
|
|
|
// Increment the block counter at the given slot (block code coverage).
|
|
BytecodeArrayBuilder& IncBlockCounter(int slot);
|
|
|
|
// Complex flow control.
|
|
BytecodeArrayBuilder& ForInEnumerate(Register receiver);
|
|
BytecodeArrayBuilder& ForInPrepare(RegisterList cache_info_triple,
|
|
int feedback_slot);
|
|
BytecodeArrayBuilder& ForInContinue(Register index, Register cache_length);
|
|
BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
|
|
RegisterList cache_type_array_pair,
|
|
int feedback_slot);
|
|
BytecodeArrayBuilder& ForInStep(Register index);
|
|
|
|
// Generators.
|
|
BytecodeArrayBuilder& SuspendGenerator(Register generator,
|
|
RegisterList registers,
|
|
int suspend_id);
|
|
BytecodeArrayBuilder& SwitchOnGeneratorState(Register generator,
|
|
BytecodeJumpTable* jump_table);
|
|
BytecodeArrayBuilder& ResumeGenerator(Register generator,
|
|
RegisterList registers);
|
|
|
|
// Creates a new handler table entry and returns a {hander_id} identifying the
|
|
// entry, so that it can be referenced by above exception handling support.
|
|
int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
|
|
|
|
// Allocates a new jump table of given |size| and |case_value_base| in the
|
|
// constant pool.
|
|
BytecodeJumpTable* AllocateJumpTable(int size, int case_value_base);
|
|
|
|
// Gets a constant pool entry.
|
|
size_t GetConstantPoolEntry(const AstRawString* raw_string);
|
|
size_t GetConstantPoolEntry(AstBigInt bigint);
|
|
size_t GetConstantPoolEntry(const Scope* scope);
|
|
size_t GetConstantPoolEntry(double number);
|
|
#define ENTRY_GETTER(NAME, ...) size_t NAME##ConstantPoolEntry();
|
|
SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
|
|
#undef ENTRY_GETTER
|
|
|
|
// Allocates a slot in the constant pool which can later be set.
|
|
size_t AllocateDeferredConstantPoolEntry();
|
|
// Sets the deferred value into an allocated constant pool entry.
|
|
void SetDeferredConstantPoolEntry(size_t entry, Handle<Object> object);
|
|
|
|
void InitializeReturnPosition(FunctionLiteral* literal);
|
|
|
|
void SetStatementPosition(Statement* stmt) {
|
|
if (stmt->position() == kNoSourcePosition) return;
|
|
latest_source_info_.MakeStatementPosition(stmt->position());
|
|
}
|
|
|
|
void SetExpressionPosition(Expression* expr) {
|
|
SetExpressionPosition(expr->position());
|
|
}
|
|
|
|
void SetExpressionPosition(int position) {
|
|
if (position == kNoSourcePosition) return;
|
|
if (!latest_source_info_.is_statement()) {
|
|
// Ensure the current expression position is overwritten with the
|
|
// latest value.
|
|
latest_source_info_.MakeExpressionPosition(position);
|
|
}
|
|
}
|
|
|
|
void SetExpressionAsStatementPosition(Expression* expr) {
|
|
if (expr->position() == kNoSourcePosition) return;
|
|
latest_source_info_.MakeStatementPosition(expr->position());
|
|
}
|
|
|
|
void SetReturnPosition(int source_position, FunctionLiteral* literal) {
|
|
if (source_position != kNoSourcePosition) {
|
|
latest_source_info_.MakeStatementPosition(source_position);
|
|
} else if (literal->return_position() != kNoSourcePosition) {
|
|
latest_source_info_.MakeStatementPosition(literal->return_position());
|
|
}
|
|
}
|
|
|
|
bool RemainderOfBlockIsDead() const {
|
|
return bytecode_array_writer_.RemainderOfBlockIsDead();
|
|
}
|
|
|
|
// Returns the raw operand value for the given register or register list.
|
|
uint32_t GetInputRegisterOperand(Register reg);
|
|
uint32_t GetOutputRegisterOperand(Register reg);
|
|
uint32_t GetInputRegisterListOperand(RegisterList reg_list);
|
|
uint32_t GetOutputRegisterListOperand(RegisterList reg_list);
|
|
|
|
// Outputs raw register transfer bytecodes without going through the register
|
|
// optimizer.
|
|
void OutputLdarRaw(Register reg);
|
|
void OutputStarRaw(Register reg);
|
|
void OutputMovRaw(Register src, Register dest);
|
|
|
|
void EmitFunctionStartSourcePosition(int position);
|
|
|
|
// Accessors
|
|
BytecodeRegisterAllocator* register_allocator() {
|
|
return ®ister_allocator_;
|
|
}
|
|
const BytecodeRegisterAllocator* register_allocator() const {
|
|
return ®ister_allocator_;
|
|
}
|
|
Zone* zone() const { return zone_; }
|
|
|
|
private:
|
|
friend class BytecodeRegisterAllocator;
|
|
template <Bytecode bytecode, AccumulatorUse accumulator_use,
|
|
OperandType... operand_types>
|
|
friend class BytecodeNodeBuilder;
|
|
|
|
const FeedbackVectorSpec* feedback_vector_spec() const {
|
|
return feedback_vector_spec_;
|
|
}
|
|
|
|
// Returns the current source position for the given |bytecode|.
|
|
V8_INLINE BytecodeSourceInfo CurrentSourcePosition(Bytecode bytecode);
|
|
|
|
#define DECLARE_BYTECODE_OUTPUT(Name, ...) \
|
|
template <typename... Operands> \
|
|
V8_INLINE BytecodeNode Create##Name##Node(Operands... operands); \
|
|
template <typename... Operands> \
|
|
V8_INLINE void Output##Name(Operands... operands); \
|
|
template <typename... Operands> \
|
|
V8_INLINE void Output##Name(BytecodeLabel* label, Operands... operands);
|
|
BYTECODE_LIST(DECLARE_BYTECODE_OUTPUT)
|
|
#undef DECLARE_OPERAND_TYPE_INFO
|
|
|
|
V8_INLINE void OutputJumpLoop(BytecodeLoopHeader* loop_header,
|
|
int loop_depth);
|
|
V8_INLINE void OutputSwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
|
|
|
|
bool RegisterIsValid(Register reg) const;
|
|
bool RegisterListIsValid(RegisterList reg_list) const;
|
|
|
|
// Sets a deferred source info which should be emitted before any future
|
|
// source info (either attached to a following bytecode or as a nop).
|
|
void SetDeferredSourceInfo(BytecodeSourceInfo source_info);
|
|
// Either attach deferred source info to node, or emit it as a nop bytecode
|
|
// if node already have valid source info.
|
|
void AttachOrEmitDeferredSourceInfo(BytecodeNode* node);
|
|
|
|
// Write bytecode to bytecode array.
|
|
void Write(BytecodeNode* node);
|
|
void WriteJump(BytecodeNode* node, BytecodeLabel* label);
|
|
void WriteJumpLoop(BytecodeNode* node, BytecodeLoopHeader* loop_header);
|
|
void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* label);
|
|
|
|
// Not implemented as the illegal bytecode is used inside internally
|
|
// to indicate a bytecode field is not valid or an error has occurred
|
|
// during bytecode generation.
|
|
BytecodeArrayBuilder& Illegal();
|
|
|
|
template <Bytecode bytecode, AccumulatorUse accumulator_use>
|
|
void PrepareToOutputBytecode();
|
|
|
|
BytecodeArrayWriter* bytecode_array_writer() {
|
|
return &bytecode_array_writer_;
|
|
}
|
|
ConstantArrayBuilder* constant_array_builder() {
|
|
return &constant_array_builder_;
|
|
}
|
|
const ConstantArrayBuilder* constant_array_builder() const {
|
|
return &constant_array_builder_;
|
|
}
|
|
HandlerTableBuilder* handler_table_builder() {
|
|
return &handler_table_builder_;
|
|
}
|
|
|
|
Zone* zone_;
|
|
FeedbackVectorSpec* feedback_vector_spec_;
|
|
bool bytecode_generated_;
|
|
ConstantArrayBuilder constant_array_builder_;
|
|
HandlerTableBuilder handler_table_builder_;
|
|
int parameter_count_;
|
|
int local_register_count_;
|
|
BytecodeRegisterAllocator register_allocator_;
|
|
BytecodeArrayWriter bytecode_array_writer_;
|
|
BytecodeRegisterOptimizer* register_optimizer_;
|
|
BytecodeSourceInfo latest_source_info_;
|
|
BytecodeSourceInfo deferred_source_info_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
|
|
};
|
|
|
|
V8_EXPORT_PRIVATE std::ostream& operator<<(
|
|
std::ostream& os, const BytecodeArrayBuilder::ToBooleanMode& mode);
|
|
|
|
} // namespace interpreter
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
|