Commit 699a91f2 authored by jgruber's avatar jgruber Committed by Commit Bot

[tasm] Add platform-independent base class TurboAssemblerBase

This class can contain members and functions common across all
platforms.

Bug: v8:6666
Change-Id: I8f232f806457164a2401f74c7140fd035ad05096
Reviewed-on: https://chromium-review.googlesource.com/1086940
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53609}
parent 502f9216
......@@ -2377,6 +2377,8 @@ v8_source_set("v8_base") {
"src/trap-handler/handler-shared.cc",
"src/trap-handler/trap-handler-internal.h",
"src/trap-handler/trap-handler.h",
"src/turbo-assembler.cc",
"src/turbo-assembler.h",
"src/type-hints.cc",
"src/type-hints.h",
"src/unicode-cache-inl.h",
......
......@@ -208,7 +208,7 @@ void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
// This is basically an inlined version of Call(Handle<Code>) that loads the
// code object into lr instead of ip.
__ Move(ip, target);
__ LookupConstant(lr, GetCode());
__ IndirectLoadConstant(lr, GetCode());
__ add(lr, lr, Operand(Code::kHeaderSize - kHeapObjectTag));
__ blx(lr);
return;
......
......@@ -11,7 +11,6 @@
#include "src/base/division-by-constant.h"
#include "src/base/utils/random-number-generator.h"
#include "src/bootstrapper.h"
#include "src/builtins/constants-table-builder.h"
#include "src/callable.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
......@@ -24,7 +23,6 @@
#include "src/objects-inl.h"
#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
#include "src/snapshot/serializer-common.h"
#include "src/snapshot/snapshot.h"
#include "src/arm/macro-assembler-arm.h"
......@@ -46,19 +44,6 @@ MacroAssembler::MacroAssembler(Isolate* isolate, void* buffer, int size,
}
}
TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object)
: Assembler(isolate, buffer, buffer_size), isolate_(isolate) {
if (create_code_object == CodeObjectRequired::kYes) {
code_object_ = Handle<HeapObject>::New(
isolate->heap()->self_reference_marker(), isolate);
}
}
TurboAssembler::TurboAssembler(IsolateData isolate_data, void* buffer,
int buffer_size)
: Assembler(isolate_data, buffer, buffer_size) {}
int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1,
Register exclusion2,
......@@ -141,39 +126,8 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
}
#ifdef V8_EMBEDDED_BUILTINS
void TurboAssembler::LookupConstant(Register destination,
Handle<HeapObject> object) {
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Before falling back to the (fairly slow) lookup from the constants table,
// check if any of the fast paths can be applied.
{
int builtin_index;
Heap::RootListIndex root_index;
if (isolate()->heap()->IsRootHandle(object, &root_index)) {
// Roots are loaded relative to the root register.
LoadRoot(destination, root_index);
return;
} else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin_index)) {
// Similar to roots, builtins may be loaded from the builtins table.
LoadBuiltin(destination, builtin_index);
return;
} else if (object.is_identical_to(code_object_) &&
Builtins::IsBuiltinId(maybe_builtin_index_)) {
// The self-reference loaded through Codevalue() may also be a builtin
// and thus viable for a fast load.
LoadBuiltin(destination, maybe_builtin_index_);
return;
}
}
// Ensure the given object is in the builtins constants table and fetch its
// index.
BuiltinsConstantsTableBuilder* builder =
isolate()->builtins_constants_table_builder();
uint32_t index = builder->AddObject(object);
void TurboAssembler::LoadFromConstantsTable(Register destination,
int constant_index) {
DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(
Heap::kBuiltinsConstantsTableRootIndex));
......@@ -183,7 +137,7 @@ void TurboAssembler::LookupConstant(Register destination,
// the target.
const uint32_t offset =
FixedArray::kHeaderSize + index * kPointerSize - kHeapObjectTag;
FixedArray::kHeaderSize + constant_index * kPointerSize - kHeapObjectTag;
const bool could_clobber_ip = !is_uint12(offset);
Register reg = destination;
......@@ -201,25 +155,11 @@ void TurboAssembler::LookupConstant(Register destination,
}
}
void TurboAssembler::LookupExternalReference(Register destination,
ExternalReference reference) {
CHECK(reference.address() !=
ExternalReference::roots_array_start(isolate()).address());
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Encode as an index into the external reference table stored on the isolate.
ExternalReferenceEncoder encoder(isolate());
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
CHECK(!v.is_from_api());
uint32_t index = v.index();
// Generate code to load from the external reference table.
void TurboAssembler::LoadExternalReference(Register destination,
int reference_index) {
int32_t roots_to_external_reference_offset =
Heap::roots_to_external_reference_table_offset() +
ExternalReferenceTable::OffsetOfEntry(index);
ExternalReferenceTable::OffsetOfEntry(reference_index);
ldr(destination,
MemOperand(kRootRegister, roots_to_external_reference_offset));
......@@ -256,7 +196,7 @@ void TurboAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
UseScratchRegisterScope temps(this);
Register scratch = temps.Acquire();
LookupConstant(scratch, code);
IndirectLoadConstant(scratch, code);
add(scratch, scratch, Operand(Code::kHeaderSize - kHeapObjectTag));
Jump(scratch, cond);
return;
......@@ -361,7 +301,7 @@ void TurboAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
// Use ip directly instead of using UseScratchRegisterScope, as we do not
// preserve scratch registers across calls.
LookupConstant(ip, code);
IndirectLoadConstant(ip, code);
add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
Call(ip, cond);
return;
......@@ -423,7 +363,7 @@ void TurboAssembler::Move(Register dst, Smi* smi) { mov(dst, Operand(smi)); }
void TurboAssembler::Move(Register dst, Handle<HeapObject> value) {
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(dst, value);
IndirectLoadConstant(dst, value);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -435,7 +375,7 @@ void TurboAssembler::Move(Register dst, ExternalReference reference) {
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList() &&
reference.address() !=
ExternalReference::roots_array_start(isolate()).address()) {
LookupExternalReference(dst, reference);
IndirectLoadExternalReference(dst, reference);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......
......@@ -9,6 +9,7 @@
#include "src/assembler.h"
#include "src/bailout-reason.h"
#include "src/globals.h"
#include "src/turbo-assembler.h"
namespace v8 {
namespace internal {
......@@ -85,21 +86,14 @@ enum TargetAddressStorageMode {
NEVER_INLINE_TARGET_ADDRESS
};
class TurboAssembler : public Assembler {
class TurboAssembler : public TurboAssemblerBase {
public:
TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object);
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size);
void set_has_frame(bool value) { has_frame_ = value; }
bool has_frame() const { return has_frame_; }
Isolate* isolate() const { return isolate_; }
CodeObjectRequired create_code_object)
: TurboAssemblerBase(isolate, buffer, buffer_size, create_code_object) {}
Handle<HeapObject> CodeObject() {
DCHECK(!code_object_.is_null());
return code_object_;
}
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size)
: TurboAssemblerBase(isolate_data, buffer, buffer_size) {}
// Activation support.
void EnterFrame(StackFrame::Type type,
......@@ -323,10 +317,11 @@ class TurboAssembler : public Assembler {
Register src_high, uint32_t shift);
#ifdef V8_EMBEDDED_BUILTINS
void LookupConstant(Register destination, Handle<HeapObject> object);
void LookupExternalReference(Register destination,
ExternalReference reference);
void LoadBuiltin(Register destination, int builtin_index);
void LoadFromConstantsTable(Register destination,
int constant_index) override;
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
#endif // V8_EMBEDDED_BUILTINS
// Returns the size of a call in instructions. Note, the value returned is
......@@ -514,8 +509,11 @@ class TurboAssembler : public Assembler {
}
// Load an object from the root table.
void LoadRoot(Register destination, Heap::RootListIndex index) override {
LoadRoot(destination, index, al);
}
void LoadRoot(Register destination, Heap::RootListIndex index,
Condition cond = al);
Condition cond);
// Jump if the register contains a smi.
void JumpIfSmi(Register value, Label* smi_label);
......@@ -552,23 +550,7 @@ class TurboAssembler : public Assembler {
void ResetSpeculationPoisonRegister();
bool root_array_available() const { return root_array_available_; }
void set_root_array_available(bool v) { root_array_available_ = v; }
void set_builtin_index(int builtin_index) {
maybe_builtin_index_ = builtin_index;
}
protected:
// This handle will be patched with the code object on installation.
Handle<HeapObject> code_object_;
private:
int maybe_builtin_index_ = -1; // May be set while generating builtins.
bool has_frame_ = false;
bool root_array_available_ = true;
Isolate* const isolate_ = nullptr;
// Compare single values and then load the fpscr flags to a register.
void VFPCompareAndLoadFlags(const SwVfpRegister src1,
const SwVfpRegister src2,
......
......@@ -8,7 +8,6 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/bootstrapper.h"
#include "src/builtins/constants-table-builder.h"
#include "src/callable.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
......@@ -20,7 +19,6 @@
#include "src/instruction-stream.h"
#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
#include "src/snapshot/serializer-common.h"
#include "src/snapshot/snapshot.h"
#include "src/arm64/macro-assembler-arm64-inl.h"
......@@ -50,19 +48,6 @@ CPURegList TurboAssembler::DefaultFPTmpList() {
return CPURegList(fp_scratch1, fp_scratch2);
}
TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object)
: Assembler(isolate, buffer, buffer_size), isolate_(isolate) {
if (create_code_object == CodeObjectRequired::kYes) {
code_object_ = Handle<HeapObject>::New(
isolate->heap()->self_reference_marker(), isolate);
}
}
TurboAssembler::TurboAssembler(IsolateData isolate_data, void* buffer,
int buffer_size)
: Assembler(isolate_data, buffer, buffer_size) {}
int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion) const {
int bytes = 0;
......@@ -365,7 +350,7 @@ void TurboAssembler::Mov(const Register& rd, const Operand& operand,
void TurboAssembler::Mov(const Register& rd, ExternalReference reference) {
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupExternalReference(rd, reference);
IndirectLoadExternalReference(rd, reference);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -1567,8 +1552,7 @@ void TurboAssembler::CanonicalizeNaN(const VRegister& dst,
Fsub(dst, src, fp_zero);
}
void TurboAssembler::LoadRoot(CPURegister destination,
Heap::RootListIndex index) {
void TurboAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
// TODO(jbramley): Most root values are constants, and can be synthesized
// without a load. Refer to the ARM back end for details.
Ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2));
......@@ -1589,7 +1573,7 @@ void TurboAssembler::Move(Register dst, Register src) { Mov(dst, src); }
void TurboAssembler::Move(Register dst, Handle<HeapObject> value) {
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(dst, value);
IndirectLoadConstant(dst, value);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -1882,77 +1866,29 @@ void TurboAssembler::CallCFunction(Register function, int num_of_reg_args,
}
#ifdef V8_EMBEDDED_BUILTINS
void TurboAssembler::LookupConstant(Register destination,
Handle<HeapObject> object) {
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Before falling back to the (fairly slow) lookup from the constants table,
// check if any of the fast paths can be applied.
{
int builtin_index;
Heap::RootListIndex root_index;
if (isolate()->heap()->IsRootHandle(object, &root_index)) {
// Roots are loaded relative to the root register.
LoadRoot(destination, root_index);
return;
} else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin_index)) {
// Similar to roots, builtins may be loaded from the builtins table.
LoadBuiltin(destination, builtin_index);
return;
} else if (object.is_identical_to(code_object_) &&
Builtins::IsBuiltinId(maybe_builtin_index_)) {
// The self-reference loaded through Codevalue() may also be a builtin
// and thus viable for a fast load.
LoadBuiltin(destination, maybe_builtin_index_);
return;
}
}
// Ensure the given object is in the builtins constants table and fetch its
// index.
BuiltinsConstantsTableBuilder* builder =
isolate()->builtins_constants_table_builder();
uint32_t index = builder->AddObject(object);
void TurboAssembler::LoadFromConstantsTable(Register destination,
int constant_index) {
DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(
Heap::kBuiltinsConstantsTableRootIndex));
LoadRoot(destination, Heap::kBuiltinsConstantsTableRootIndex);
Ldr(destination, FieldMemOperand(destination, FixedArray::kHeaderSize +
index * kPointerSize));
Ldr(destination,
FieldMemOperand(destination,
FixedArray::kHeaderSize + constant_index * kPointerSize));
}
void TurboAssembler::LookupExternalReference(Register destination,
ExternalReference reference) {
CHECK(reference.address() !=
ExternalReference::roots_array_start(isolate()).address());
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Encode as an index into the external reference table stored on the isolate.
ExternalReferenceEncoder encoder(isolate());
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
CHECK(!v.is_from_api());
uint32_t index = v.index();
// Generate code to load from the external reference table.
void TurboAssembler::LoadExternalReference(Register destination,
int reference_index) {
int32_t roots_to_external_reference_offset =
Heap::roots_to_external_reference_table_offset() +
ExternalReferenceTable::OffsetOfEntry(index);
ExternalReferenceTable::OffsetOfEntry(reference_index);
Ldr(destination,
MemOperand(kRootRegister, roots_to_external_reference_offset));
}
void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
DCHECK(Builtins::IsBuiltinId(builtin_index));
int32_t roots_to_builtins_offset =
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
Ldr(destination, MemOperand(kRootRegister, roots_to_builtins_offset));
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -2015,7 +1951,7 @@ void TurboAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
UseScratchRegisterScope temps(this);
Register scratch = temps.AcquireX();
LookupConstant(scratch, code);
IndirectLoadConstant(scratch, code);
Add(scratch, scratch, Operand(Code::kHeaderSize - kHeapObjectTag));
Jump(scratch, cond);
return;
......@@ -2088,7 +2024,7 @@ void TurboAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode) {
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
UseScratchRegisterScope temps(this);
Register scratch = temps.AcquireX();
LookupConstant(scratch, code);
IndirectLoadConstant(scratch, code);
Add(scratch, scratch, Operand(Code::kHeaderSize - kHeapObjectTag));
Call(scratch);
return;
......
......@@ -11,6 +11,7 @@
#include "src/bailout-reason.h"
#include "src/base/bits.h"
#include "src/globals.h"
#include "src/turbo-assembler.h"
// Simulator specific helpers.
#if USE_SIMULATOR
......@@ -172,11 +173,14 @@ enum PreShiftImmMode {
kAnyShift // Allow any pre-shift.
};
class TurboAssembler : public Assembler {
class TurboAssembler : public TurboAssemblerBase {
public:
TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object);
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size);
CodeObjectRequired create_code_object)
: TurboAssemblerBase(isolate, buffer, buffer_size, create_code_object) {}
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size)
: TurboAssemblerBase(isolate_data, buffer, buffer_size) {}
// The Abort method should call a V8 runtime function, but the CallRuntime
// mechanism depends on CEntry. If use_real_aborts is false, Abort will
......@@ -199,16 +203,6 @@ class TurboAssembler : public Assembler {
TurboAssembler* tasm_;
};
void set_has_frame(bool value) { has_frame_ = value; }
bool has_frame() const { return has_frame_; }
Isolate* isolate() const { return isolate_; }
Handle<HeapObject> CodeObject() {
DCHECK(!code_object_.is_null());
return code_object_;
}
#if DEBUG
void set_allow_macro_instructions(bool value) {
allow_macro_instructions_ = value;
......@@ -881,10 +875,11 @@ class TurboAssembler : public Assembler {
void Movi(const VRegister& vd, uint64_t hi, uint64_t lo);
#ifdef V8_EMBEDDED_BUILTINS
void LookupConstant(Register destination, Handle<HeapObject> object);
void LookupExternalReference(Register destination,
ExternalReference reference);
void LoadBuiltin(Register destination, int builtin_index);
void LoadFromConstantsTable(Register destination,
int constant_index) override;
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
#endif // V8_EMBEDDED_BUILTINS
void Jump(Register target, Condition cond = al);
......@@ -1166,7 +1161,7 @@ class TurboAssembler : public Assembler {
#undef DECLARE_FUNCTION
// Load an object from the root table.
void LoadRoot(CPURegister destination, Heap::RootListIndex index);
void LoadRoot(Register destination, Heap::RootListIndex index) override;
inline void Ret(const Register& xn = lr);
......@@ -1230,13 +1225,6 @@ class TurboAssembler : public Assembler {
void ResetSpeculationPoisonRegister();
bool root_array_available() const { return root_array_available_; }
void set_root_array_available(bool v) { root_array_available_ = v; }
void set_builtin_index(int builtin_index) {
maybe_builtin_index_ = builtin_index;
}
protected:
// The actual Push and Pop implementations. These don't generate any code
// other than that required for the push or pop. This allows
......@@ -1269,14 +1257,7 @@ class TurboAssembler : public Assembler {
// have mixed types. The format string (x0) should not be included.
void CallPrintf(int arg_count = 0, const CPURegister* args = nullptr);
// This handle will be patched with the code object on installation.
Handle<HeapObject> code_object_;
private:
int maybe_builtin_index_ = -1; // May be set while generating builtins.
bool has_frame_ = false;
bool root_array_available_ = true;
Isolate* const isolate_ = nullptr;
#if DEBUG
// Tell whether any of the macro instruction can be used. When false the
// MacroAssembler will assert if a method which can emit a variable number
......
......@@ -41,20 +41,7 @@ MacroAssembler::MacroAssembler(Isolate* isolate, void* buffer, int size,
}
}
TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object)
: Assembler(isolate, buffer, buffer_size), isolate_(isolate) {
if (create_code_object == CodeObjectRequired::kYes) {
code_object_ = Handle<HeapObject>::New(
isolate->heap()->self_reference_marker(), isolate);
}
}
TurboAssembler::TurboAssembler(IsolateData isolate_data, void* buffer,
int buffer_size)
: Assembler(isolate_data, buffer, buffer_size) {}
void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
void TurboAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
Handle<Object> object = isolate()->heap()->root_handle(index);
if (object->IsHeapObject()) {
......
......@@ -9,6 +9,7 @@
#include "src/bailout-reason.h"
#include "src/globals.h"
#include "src/ia32/assembler-ia32.h"
#include "src/turbo-assembler.h"
namespace v8 {
namespace internal {
......@@ -49,21 +50,14 @@ bool AreAliased(Register reg1, Register reg2, Register reg3 = no_reg,
Register reg8 = no_reg);
#endif
class TurboAssembler : public Assembler {
class TurboAssembler : public TurboAssemblerBase {
public:
TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object);
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size);
void set_has_frame(bool value) { has_frame_ = value; }
bool has_frame() const { return has_frame_; }
Isolate* isolate() const { return isolate_; }
CodeObjectRequired create_code_object)
: TurboAssemblerBase(isolate, buffer, buffer_size, create_code_object) {}
Handle<HeapObject> CodeObject() {
DCHECK(!code_object_.is_null());
return code_object_;
}
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size)
: TurboAssemblerBase(isolate_data, buffer, buffer_size) {}
void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
Label* condition_met,
......@@ -202,6 +196,8 @@ class TurboAssembler : public Assembler {
void Ret();
void LoadRoot(Register destination, Heap::RootListIndex index) override;
// Return and drop arguments from stack, where the number of arguments
// may be bigger than 2^16 - 1. Requires a scratch register.
void Ret(int bytes_dropped, Register scratch);
......@@ -367,23 +363,6 @@ class TurboAssembler : public Assembler {
void ComputeCodeStartAddress(Register dst);
void ResetSpeculationPoisonRegister();
bool root_array_available() const { return root_array_available_; }
void set_root_array_available(bool v) { root_array_available_ = v; }
void set_builtin_index(int builtin_index) {
maybe_builtin_index_ = builtin_index;
}
protected:
// This handle will be patched with the code object on installation.
Handle<HeapObject> code_object_;
private:
int maybe_builtin_index_ = -1; // May be set while generating builtins.
bool has_frame_ = false;
bool root_array_available_ = false;
Isolate* const isolate_ = nullptr;
};
// MacroAssembler implements a collection of frequently used macros.
......@@ -403,7 +382,6 @@ class MacroAssembler : public TurboAssembler {
void Set(Operand dst, int32_t x) { mov(dst, Immediate(x)); }
// Operations on roots in the root-array.
void LoadRoot(Register destination, Heap::RootListIndex index);
void CompareRoot(Register with, Register scratch, Heap::RootListIndex index);
// These methods can only be used with constant roots (i.e. non-writable
// and not in new space).
......
......@@ -214,7 +214,7 @@ void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
// This is basically an inlined version of Call(Handle<Code>) that loads the
// code object into kScratchReg instead of t9.
__ Move(t9, target);
__ LookupConstant(kScratchReg, GetCode());
__ IndirectLoadConstant(kScratchReg, GetCode());
__ Call(kScratchReg, Code::kHeaderSize - kHeapObjectTag);
return;
}
......
......@@ -9,7 +9,6 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/bootstrapper.h"
#include "src/builtins/constants-table-builder.h"
#include "src/callable.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
......@@ -21,7 +20,6 @@
#include "src/mips/macro-assembler-mips.h"
#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
#include "src/snapshot/serializer-common.h"
#include "src/snapshot/snapshot.h"
namespace v8 {
......@@ -41,19 +39,6 @@ MacroAssembler::MacroAssembler(Isolate* isolate, void* buffer, int size,
}
}
TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object)
: Assembler(isolate, buffer, buffer_size), isolate_(isolate) {
if (create_code_object == CodeObjectRequired::kYes) {
code_object_ = Handle<HeapObject>::New(
isolate->heap()->self_reference_marker(), isolate);
}
}
TurboAssembler::TurboAssembler(IsolateData isolate_data, void* buffer,
int buffer_size)
: Assembler(isolate_data, buffer, buffer_size) {}
static inline bool IsZero(const Operand& rt) {
if (rt.is_reg()) {
return rt.rm() == zero_reg;
......@@ -1338,7 +1323,7 @@ void TurboAssembler::Sc(Register rd, const MemOperand& rs) {
void TurboAssembler::li(Register dst, Handle<HeapObject> value, LiFlags mode) {
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(dst, value);
IndirectLoadConstant(dst, value);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -1348,7 +1333,7 @@ void TurboAssembler::li(Register dst, Handle<HeapObject> value, LiFlags mode) {
void TurboAssembler::li(Register dst, ExternalReference value, LiFlags mode) {
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupExternalReference(dst, value);
IndirectLoadExternalReference(dst, value);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -3613,77 +3598,29 @@ bool TurboAssembler::BranchAndLinkShortCheck(int32_t offset, Label* L,
}
#ifdef V8_EMBEDDED_BUILTINS
void TurboAssembler::LookupConstant(Register destination,
Handle<HeapObject> object) {
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Before falling back to the (fairly slow) lookup from the constants table,
// check if any of the fast paths can be applied.
{
int builtin_index;
Heap::RootListIndex root_index;
if (isolate()->heap()->IsRootHandle(object, &root_index)) {
// Roots are loaded relative to the root register.
LoadRoot(destination, root_index);
return;
} else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin_index)) {
// Similar to roots, builtins may be loaded from the builtins table.
LoadBuiltin(destination, builtin_index);
return;
} else if (object.is_identical_to(code_object_) &&
Builtins::IsBuiltinId(maybe_builtin_index_)) {
// The self-reference loaded through Codevalue() may also be a builtin
// and thus viable for a fast load.
LoadBuiltin(destination, maybe_builtin_index_);
return;
}
}
// Ensure the given object is in the builtins constants table and fetch its
// index.
BuiltinsConstantsTableBuilder* builder =
isolate()->builtins_constants_table_builder();
uint32_t index = builder->AddObject(object);
void TurboAssembler::LoadFromConstantsTable(Register destination,
int constant_index) {
DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(
Heap::kBuiltinsConstantsTableRootIndex));
LoadRoot(destination, Heap::kBuiltinsConstantsTableRootIndex);
lw(destination, FieldMemOperand(destination, FixedArray::kHeaderSize +
index * kPointerSize));
lw(destination,
FieldMemOperand(destination,
FixedArray::kHeaderSize + constant_index * kPointerSize));
}
void TurboAssembler::LookupExternalReference(Register destination,
ExternalReference reference) {
CHECK(reference.address() !=
ExternalReference::roots_array_start(isolate()).address());
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Encode as an index into the external reference table stored on the isolate.
ExternalReferenceEncoder encoder(isolate());
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
CHECK(!v.is_from_api());
uint32_t index = v.index();
// Generate code to load from the external reference table.
void TurboAssembler::LoadExternalReference(Register destination,
int reference_index) {
int32_t roots_to_external_reference_offset =
Heap::roots_to_external_reference_table_offset() +
ExternalReferenceTable::OffsetOfEntry(index);
ExternalReferenceTable::OffsetOfEntry(reference_index);
lw(destination,
MemOperand(kRootRegister, roots_to_external_reference_offset));
}
void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
DCHECK(Builtins::IsBuiltinId(builtin_index));
int32_t roots_to_builtins_offset =
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
lw(destination, MemOperand(kRootRegister, roots_to_builtins_offset));
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -3817,7 +3754,7 @@ void TurboAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
DCHECK(RelocInfo::IsCodeTarget(rmode));
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(t9, code);
IndirectLoadConstant(t9, code);
Jump(t9, Code::kHeaderSize - kHeapObjectTag, cond, rs, rt, bd);
return;
} else if (!isolate()->serializer_enabled()) {
......@@ -3987,7 +3924,7 @@ void TurboAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
BlockTrampolinePoolScope block_trampoline_pool(this);
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(t9, code);
IndirectLoadConstant(t9, code);
Call(t9, Code::kHeaderSize - kHeapObjectTag, cond, rs, rt, bd);
return;
} else if (!isolate()->serializer_enabled()) {
......
......@@ -8,6 +8,7 @@
#include "src/assembler.h"
#include "src/globals.h"
#include "src/mips/assembler-mips.h"
#include "src/turbo-assembler.h"
namespace v8 {
namespace internal {
......@@ -126,21 +127,14 @@ inline MemOperand CFunctionArgumentOperand(int index) {
return MemOperand(sp, offset);
}
class TurboAssembler : public Assembler {
class TurboAssembler : public TurboAssemblerBase {
public:
TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object);
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size);
void set_has_frame(bool value) { has_frame_ = value; }
bool has_frame() const { return has_frame_; }
CodeObjectRequired create_code_object)
: TurboAssemblerBase(isolate, buffer, buffer_size, create_code_object) {}
Isolate* isolate() const { return isolate_; }
Handle<HeapObject> CodeObject() {
DCHECK(!code_object_.is_null());
return code_object_;
}
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size)
: TurboAssemblerBase(isolate_data, buffer, buffer_size) {}
// Activation support.
void EnterFrame(StackFrame::Type type);
......@@ -252,10 +246,11 @@ class TurboAssembler : public Assembler {
void li(Register dst, ExternalReference value, LiFlags mode = OPTIMIZE_SIZE);
#ifdef V8_EMBEDDED_BUILTINS
void LookupConstant(Register destination, Handle<HeapObject> object);
void LookupExternalReference(Register destination,
ExternalReference reference);
void LoadBuiltin(Register destination, int builtin_index);
void LoadFromConstantsTable(Register destination,
int constant_index) override;
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
#endif // V8_EMBEDDED_BUILTINS
// Jump, Call, and Ret pseudo instructions implementing inter-working.
......@@ -815,7 +810,7 @@ class TurboAssembler : public Assembler {
Func GetLabelFunction);
// Load an object from the root table.
void LoadRoot(Register destination, Heap::RootListIndex index);
void LoadRoot(Register destination, Heap::RootListIndex index) override;
void LoadRoot(Register destination, Heap::RootListIndex index, Condition cond,
Register src1, const Operand& src2);
......@@ -848,13 +843,6 @@ class TurboAssembler : public Assembler {
void ResetSpeculationPoisonRegister();
bool root_array_available() const { return root_array_available_; }
void set_root_array_available(bool v) { root_array_available_ = v; }
void set_builtin_index(int builtin_index) {
maybe_builtin_index_ = builtin_index;
}
protected:
void BranchLong(Label* L, BranchDelaySlot bdslot);
......@@ -862,14 +850,7 @@ class TurboAssembler : public Assembler {
inline int32_t GetOffset(int32_t offset, Label* L, OffsetSize bits);
// This handle will be patched with the code object on installation.
Handle<HeapObject> code_object_;
private:
int maybe_builtin_index_ = -1; // May be set while generating builtins.
bool has_frame_ = false;
bool root_array_available_ = true;
Isolate* const isolate_ = nullptr;
bool has_double_zero_reg_set_ = false;
void CallCFunctionHelper(Register function_base, int16_t function_offset,
......
......@@ -213,7 +213,7 @@ void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
// This is basically an inlined version of Call(Handle<Code>) that loads the
// code object into kScratchReg instead of t9.
__ Move(t9, target);
__ LookupConstant(kScratchReg, GetCode());
__ IndirectLoadConstant(kScratchReg, GetCode());
__ Daddu(kScratchReg, kScratchReg,
Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(kScratchReg);
......
......@@ -9,7 +9,6 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/bootstrapper.h"
#include "src/builtins/constants-table-builder.h"
#include "src/callable.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
......@@ -21,7 +20,6 @@
#include "src/mips64/macro-assembler-mips64.h"
#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
#include "src/snapshot/serializer-common.h"
#include "src/snapshot/snapshot.h"
namespace v8 {
......@@ -41,19 +39,6 @@ MacroAssembler::MacroAssembler(Isolate* isolate, void* buffer, int size,
}
}
TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object)
: Assembler(isolate, buffer, buffer_size), isolate_(isolate) {
if (create_code_object == CodeObjectRequired::kYes) {
code_object_ = Handle<HeapObject>::New(
isolate->heap()->self_reference_marker(), isolate);
}
}
TurboAssembler::TurboAssembler(IsolateData isolate_data, void* buffer,
int buffer_size)
: Assembler(isolate_data, buffer, buffer_size) {}
static inline bool IsZero(const Operand& rt) {
if (rt.is_reg()) {
return rt.rm() == zero_reg;
......@@ -1577,7 +1562,7 @@ void TurboAssembler::Scd(Register rd, const MemOperand& rs) {
void TurboAssembler::li(Register dst, Handle<HeapObject> value, LiFlags mode) {
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(dst, value);
IndirectLoadConstant(dst, value);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -1587,7 +1572,7 @@ void TurboAssembler::li(Register dst, Handle<HeapObject> value, LiFlags mode) {
void TurboAssembler::li(Register dst, ExternalReference value, LiFlags mode) {
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupExternalReference(dst, value);
IndirectLoadExternalReference(dst, value);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -4122,77 +4107,29 @@ bool TurboAssembler::BranchAndLinkShortCheck(int32_t offset, Label* L,
}
#ifdef V8_EMBEDDED_BUILTINS
void TurboAssembler::LookupConstant(Register destination,
Handle<HeapObject> object) {
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Before falling back to the (fairly slow) lookup from the constants table,
// check if any of the fast paths can be applied.
{
int builtin_index;
Heap::RootListIndex root_index;
if (isolate()->heap()->IsRootHandle(object, &root_index)) {
// Roots are loaded relative to the root register.
LoadRoot(destination, root_index);
return;
} else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin_index)) {
// Similar to roots, builtins may be loaded from the builtins table.
LoadBuiltin(destination, builtin_index);
return;
} else if (object.is_identical_to(code_object_) &&
Builtins::IsBuiltinId(maybe_builtin_index_)) {
// The self-reference loaded through Codevalue() may also be a builtin
// and thus viable for a fast load.
LoadBuiltin(destination, maybe_builtin_index_);
return;
}
}
// Ensure the given object is in the builtins constants table and fetch its
// index.
BuiltinsConstantsTableBuilder* builder =
isolate()->builtins_constants_table_builder();
uint32_t index = builder->AddObject(object);
void TurboAssembler::LoadFromConstantsTable(Register destination,
int constant_index) {
DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(
Heap::kBuiltinsConstantsTableRootIndex));
LoadRoot(destination, Heap::kBuiltinsConstantsTableRootIndex);
Ld(destination, FieldMemOperand(destination, FixedArray::kHeaderSize +
index * kPointerSize));
Ld(destination,
FieldMemOperand(destination,
FixedArray::kHeaderSize + constant_index * kPointerSize));
}
void TurboAssembler::LookupExternalReference(Register destination,
ExternalReference reference) {
CHECK(reference.address() !=
ExternalReference::roots_array_start(isolate()).address());
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Encode as an index into the external reference table stored on the isolate.
ExternalReferenceEncoder encoder(isolate());
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
CHECK(!v.is_from_api());
uint32_t index = v.index();
// Generate code to load from the external reference table.
void TurboAssembler::LoadExternalReference(Register destination,
int reference_index) {
int32_t roots_to_external_reference_offset =
Heap::roots_to_external_reference_table_offset() +
ExternalReferenceTable::OffsetOfEntry(index);
ExternalReferenceTable::OffsetOfEntry(reference_index);
Ld(destination,
MemOperand(kRootRegister, roots_to_external_reference_offset));
}
void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
DCHECK(Builtins::IsBuiltinId(builtin_index));
int32_t roots_to_builtins_offset =
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
Ld(destination, MemOperand(kRootRegister, roots_to_builtins_offset));
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -4247,7 +4184,7 @@ void TurboAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
DCHECK(RelocInfo::IsCodeTarget(rmode));
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(t9, code);
IndirectLoadConstant(t9, code);
Daddu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag));
Jump(t9, cond, rs, rt, bd);
return;
......@@ -4350,7 +4287,7 @@ void TurboAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
BlockTrampolinePoolScope block_trampoline_pool(this);
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(t9, code);
IndirectLoadConstant(t9, code);
Daddu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag));
Call(t9, cond, rs, rt, bd);
return;
......
......@@ -8,6 +8,7 @@
#include "src/assembler.h"
#include "src/globals.h"
#include "src/mips64/assembler-mips64.h"
#include "src/turbo-assembler.h"
namespace v8 {
namespace internal {
......@@ -143,21 +144,14 @@ inline MemOperand CFunctionArgumentOperand(int index) {
return MemOperand(sp, offset);
}
class TurboAssembler : public Assembler {
class TurboAssembler : public TurboAssemblerBase {
public:
TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object);
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size);
void set_has_frame(bool value) { has_frame_ = value; }
bool has_frame() const { return has_frame_; }
CodeObjectRequired create_code_object)
: TurboAssemblerBase(isolate, buffer, buffer_size, create_code_object) {}
Isolate* isolate() const { return isolate_; }
Handle<HeapObject> CodeObject() {
DCHECK(!code_object_.is_null());
return code_object_;
}
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size)
: TurboAssemblerBase(isolate_data, buffer, buffer_size) {}
// Activation support.
void EnterFrame(StackFrame::Type type);
......@@ -272,10 +266,11 @@ class TurboAssembler : public Assembler {
void li(Register dst, ExternalReference value, LiFlags mode = OPTIMIZE_SIZE);
#ifdef V8_EMBEDDED_BUILTINS
void LookupConstant(Register destination, Handle<HeapObject> object);
void LookupExternalReference(Register destination,
ExternalReference reference);
void LoadBuiltin(Register destination, int builtin_index);
void LoadFromConstantsTable(Register destination,
int constant_index) override;
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
#endif // V8_EMBEDDED_BUILTINS
// Jump, Call, and Ret pseudo instructions implementing inter-working.
......@@ -785,7 +780,7 @@ class TurboAssembler : public Assembler {
Func GetLabelFunction);
// Load an object from the root table.
void LoadRoot(Register destination, Heap::RootListIndex index);
void LoadRoot(Register destination, Heap::RootListIndex index) override;
void LoadRoot(Register destination, Heap::RootListIndex index, Condition cond,
Register src1, const Operand& src2);
......@@ -863,25 +858,11 @@ class TurboAssembler : public Assembler {
void ResetSpeculationPoisonRegister();
bool root_array_available() const { return root_array_available_; }
void set_root_array_available(bool v) { root_array_available_ = v; }
void set_builtin_index(int builtin_index) {
maybe_builtin_index_ = builtin_index;
}
protected:
inline Register GetRtAsRegisterHelper(const Operand& rt, Register scratch);
inline int32_t GetOffset(int32_t offset, Label* L, OffsetSize bits);
// This handle will be patched with the code object on installation.
Handle<HeapObject> code_object_;
private:
int maybe_builtin_index_ = -1; // May be set while generating builtins.
bool has_frame_ = false;
bool root_array_available_ = true;
Isolate* const isolate_ = nullptr;
bool has_double_zero_reg_set_ = false;
void CompareF(SecondaryField sizeField, FPUCondition cc, FPURegister cmp1,
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/turbo-assembler.h"
#include "src/builtins/builtins.h"
#include "src/builtins/constants-table-builder.h"
#include "src/heap/heap-inl.h"
#include "src/snapshot/serializer-common.h"
namespace v8 {
namespace internal {
TurboAssemblerBase::TurboAssemblerBase(Isolate* isolate, void* buffer,
int buffer_size,
CodeObjectRequired create_code_object)
: Assembler(isolate, buffer, buffer_size), isolate_(isolate) {
if (create_code_object == CodeObjectRequired::kYes) {
code_object_ = Handle<HeapObject>::New(
isolate->heap()->self_reference_marker(), isolate);
}
}
TurboAssemblerBase::TurboAssemblerBase(IsolateData isolate_data, void* buffer,
int buffer_size)
: Assembler(isolate_data, buffer, buffer_size) {}
#ifdef V8_EMBEDDED_BUILTINS
void TurboAssemblerBase::IndirectLoadConstant(Register destination,
Handle<HeapObject> object) {
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Before falling back to the (fairly slow) lookup from the constants table,
// check if any of the fast paths can be applied.
int builtin_index;
Heap::RootListIndex root_index;
if (isolate()->heap()->IsRootHandle(object, &root_index)) {
// Roots are loaded relative to the root register.
LoadRoot(destination, root_index);
} else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin_index)) {
// Similar to roots, builtins may be loaded from the builtins table.
LoadBuiltin(destination, builtin_index);
} else if (object.is_identical_to(code_object_) &&
Builtins::IsBuiltinId(maybe_builtin_index_)) {
// The self-reference loaded through Codevalue() may also be a builtin
// and thus viable for a fast load.
LoadBuiltin(destination, maybe_builtin_index_);
} else {
// Ensure the given object is in the builtins constants table and fetch its
// index.
BuiltinsConstantsTableBuilder* builder =
isolate()->builtins_constants_table_builder();
uint32_t index = builder->AddObject(object);
// Slow load from the constants table.
LoadFromConstantsTable(destination, index);
}
}
void TurboAssemblerBase::IndirectLoadExternalReference(
Register destination, ExternalReference reference) {
CHECK(reference.address() !=
ExternalReference::roots_array_start(isolate()).address());
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Encode as an index into the external reference table stored on the isolate.
ExternalReferenceEncoder encoder(isolate());
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
CHECK(!v.is_from_api());
// TODO(jgruber, v8:6666): Addresses within the isolate can be loaded through
// an offset from the roots pointer, skipping one level of indirection.
LoadExternalReference(destination, v.index());
}
#endif // V8_EMBEDDED_BUILTINS
} // namespace internal
} // namespace v8
// Copyright 2018 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_TURBO_ASSEMBLER_H_
#define V8_TURBO_ASSEMBLER_H_
#include "src/assembler-arch.h"
#include "src/heap/heap.h"
namespace v8 {
namespace internal {
// Common base class for platform-specific TurboAssemblers containing
// platform-independent bits.
class TurboAssemblerBase : public Assembler {
public:
Isolate* isolate() const { return isolate_; }
Handle<HeapObject> CodeObject() const {
DCHECK(!code_object_.is_null());
return code_object_;
}
bool root_array_available() const { return root_array_available_; }
void set_root_array_available(bool v) { root_array_available_ = v; }
void set_builtin_index(int i) { maybe_builtin_index_ = i; }
void set_has_frame(bool v) { has_frame_ = v; }
bool has_frame() const { return has_frame_; }
#ifdef V8_EMBEDDED_BUILTINS
// Loads the given constant or external reference without embedding its direct
// pointer. The produced code is isolate-independent.
void IndirectLoadConstant(Register destination, Handle<HeapObject> object);
void IndirectLoadExternalReference(Register destination,
ExternalReference reference);
virtual void LoadFromConstantsTable(Register destination,
int constant_index) = 0;
virtual void LoadExternalReference(Register destination,
int reference_index) = 0;
virtual void LoadBuiltin(Register destination, int builtin_index) = 0;
#endif // V8_EMBEDDED_BUILTINS
virtual void LoadRoot(Register destination, Heap::RootListIndex index) = 0;
protected:
TurboAssemblerBase(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object);
TurboAssemblerBase(IsolateData isolate_data, void* buffer, int buffer_size);
Isolate* const isolate_ = nullptr;
// This handle will be patched with the code object on installation.
Handle<HeapObject> code_object_;
// Whether kRootRegister has been initialized.
bool root_array_available_ = true;
// May be set while generating builtins.
int maybe_builtin_index_ = Builtins::kNoBuiltinId;
bool has_frame_ = false;
DISALLOW_IMPLICIT_CONSTRUCTORS(TurboAssemblerBase);
};
} // namespace internal
} // namespace v8
#endif // V8_TURBO_ASSEMBLER_H_
......@@ -8,7 +8,6 @@
#include "src/base/division-by-constant.h"
#include "src/base/utils/random-number-generator.h"
#include "src/bootstrapper.h"
#include "src/builtins/constants-table-builder.h"
#include "src/callable.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
......@@ -20,7 +19,6 @@
#include "src/instruction-stream.h"
#include "src/objects-inl.h"
#include "src/register-configuration.h"
#include "src/snapshot/serializer-common.h"
#include "src/snapshot/snapshot.h"
#include "src/x64/assembler-x64.h"
......@@ -79,19 +77,6 @@ MacroAssembler::MacroAssembler(Isolate* isolate, void* buffer, int size,
}
}
TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object)
: Assembler(isolate, buffer, buffer_size), isolate_(isolate) {
if (create_code_object == CodeObjectRequired::kYes) {
code_object_ = Handle<HeapObject>::New(
isolate->heap()->self_reference_marker(), isolate);
}
}
TurboAssembler::TurboAssembler(IsolateData isolate_data, void* buffer,
int buffer_size)
: Assembler(isolate_data, buffer, buffer_size) {}
static const int64_t kInvalidRootRegisterDelta = -1;
int64_t TurboAssembler::RootRegisterDelta(ExternalReference other) {
......@@ -127,7 +112,7 @@ void MacroAssembler::Load(Register destination, ExternalReference source) {
// Safe code.
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupExternalReference(kScratchRegister, source);
IndirectLoadExternalReference(kScratchRegister, source);
movp(destination, Operand(kScratchRegister, 0));
return;
}
......@@ -159,66 +144,21 @@ void MacroAssembler::Store(ExternalReference destination, Register source) {
}
#ifdef V8_EMBEDDED_BUILTINS
void TurboAssembler::LookupConstant(Register destination,
Handle<HeapObject> object) {
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Before falling back to the (fairly slow) lookup from the constants table,
// check if any of the fast paths can be applied.
{
int builtin_index;
Heap::RootListIndex root_index;
if (isolate()->heap()->IsRootHandle(object, &root_index)) {
// Roots are loaded relative to the root register.
LoadRoot(destination, root_index);
return;
} else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin_index)) {
// Similar to roots, builtins may be loaded from the builtins table.
LoadBuiltin(destination, builtin_index);
return;
} else if (object.is_identical_to(code_object_) &&
Builtins::IsBuiltinId(maybe_builtin_index_)) {
// The self-reference loaded through Codevalue() may also be a builtin
// and thus viable for a fast load.
LoadBuiltin(destination, maybe_builtin_index_);
return;
}
}
// Ensure the given object is in the builtins constants table and fetch its
// index.
BuiltinsConstantsTableBuilder* builder =
isolate()->builtins_constants_table_builder();
uint32_t index = builder->AddObject(object);
void TurboAssembler::LoadFromConstantsTable(Register destination,
int constant_index) {
DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(
Heap::kBuiltinsConstantsTableRootIndex));
LoadRoot(destination, Heap::kBuiltinsConstantsTableRootIndex);
movp(destination, FieldOperand(destination, FixedArray::kHeaderSize +
index * kPointerSize));
movp(destination,
FieldOperand(destination,
FixedArray::kHeaderSize + constant_index * kPointerSize));
}
void TurboAssembler::LookupExternalReference(Register destination,
ExternalReference reference) {
CHECK(reference.address() !=
ExternalReference::roots_array_start(isolate()).address());
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Encode as an index into the external reference table stored on the isolate.
ExternalReferenceEncoder encoder(isolate());
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
CHECK(!v.is_from_api());
uint32_t index = v.index();
// Generate code to load from the external reference table.
void TurboAssembler::LoadExternalReference(Register destination,
int reference_index) {
int32_t roots_to_external_reference_offset =
Heap::roots_to_external_reference_table_offset() - kRootRegisterBias +
ExternalReferenceTable::OffsetOfEntry(index);
ExternalReferenceTable::OffsetOfEntry(reference_index);
movp(destination, Operand(kRootRegister, roots_to_external_reference_offset));
}
......@@ -246,7 +186,7 @@ void TurboAssembler::LoadAddress(Register destination,
// Safe code.
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupExternalReference(destination, source);
IndirectLoadExternalReference(destination, source);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -1123,7 +1063,7 @@ void TurboAssembler::Move(Register dst, ExternalReference ext) {
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList() &&
ext.address() !=
ExternalReference::roots_array_start(isolate()).address()) {
LookupExternalReference(dst, ext);
IndirectLoadExternalReference(dst, ext);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -1433,7 +1373,7 @@ void TurboAssembler::Move(Register result, Handle<HeapObject> object,
RelocInfo::Mode rmode) {
#ifdef V8_EMBEDDED_BUILTINS
if (root_array_available_ && isolate()->ShouldLoadConstantsFromRootList()) {
LookupConstant(result, object);
IndirectLoadConstant(result, object);
return;
}
#endif // V8_EMBEDDED_BUILTINS
......@@ -1587,7 +1527,7 @@ void TurboAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode,
if (cc == never) return;
j(NegateCondition(cc), &skip, Label::kNear);
}
LookupConstant(kScratchRegister, code_object);
IndirectLoadConstant(kScratchRegister, code_object);
leap(kScratchRegister, FieldOperand(kScratchRegister, Code::kHeaderSize));
jmp(kScratchRegister);
bind(&skip);
......@@ -1656,7 +1596,7 @@ void TurboAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
// are patched up to point directly to the off-heap instruction start.
// Note: It is safe to dereference code_object above since code generation
// for builtins and code stubs happens on the main thread.
LookupConstant(kScratchRegister, code_object);
IndirectLoadConstant(kScratchRegister, code_object);
leap(kScratchRegister, FieldOperand(kScratchRegister, Code::kHeaderSize));
call(kScratchRegister);
return;
......
......@@ -8,6 +8,7 @@
#include "src/bailout-reason.h"
#include "src/base/flags.h"
#include "src/globals.h"
#include "src/turbo-assembler.h"
#include "src/x64/assembler-x64.h"
namespace v8 {
......@@ -122,21 +123,14 @@ class StackArgumentsAccessor BASE_EMBEDDED {
DISALLOW_IMPLICIT_CONSTRUCTORS(StackArgumentsAccessor);
};
class TurboAssembler : public Assembler {
class TurboAssembler : public TurboAssemblerBase {
public:
TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
CodeObjectRequired create_code_object);
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size);
void set_has_frame(bool value) { has_frame_ = value; }
bool has_frame() const { return has_frame_; }
Isolate* isolate() const { return isolate_; }
CodeObjectRequired create_code_object)
: TurboAssemblerBase(isolate, buffer, buffer_size, create_code_object) {}
Handle<HeapObject> CodeObject() {
DCHECK(!code_object_.is_null());
return code_object_;
}
TurboAssembler(IsolateData isolate_data, void* buffer, int buffer_size)
: TurboAssemblerBase(isolate_data, buffer, buffer_size) {}
template <typename Dst, typename... Args>
struct AvxHelper {
......@@ -233,7 +227,7 @@ class TurboAssembler : public Assembler {
void Set(Operand dst, intptr_t x);
// Operations on roots in the root-array.
void LoadRoot(Register destination, Heap::RootListIndex index);
void LoadRoot(Register destination, Heap::RootListIndex index) override;
void LoadRoot(Operand destination, Heap::RootListIndex index) {
LoadRoot(kScratchRegister, index);
movp(destination, kScratchRegister);
......@@ -367,10 +361,11 @@ class TurboAssembler : public Assembler {
void LoadAddress(Register destination, ExternalReference source);
#ifdef V8_EMBEDDED_BUILTINS
void LookupConstant(Register destination, Handle<HeapObject> object);
void LookupExternalReference(Register destination,
ExternalReference reference);
void LoadBuiltin(Register destination, int builtin_index);
void LoadFromConstantsTable(Register destination,
int constant_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
void LoadExternalReference(Register destination,
int reference_index) override;
#endif // V8_EMBEDDED_BUILTINS
// Operand pointing to an external reference.
......@@ -530,30 +525,16 @@ class TurboAssembler : public Assembler {
void ResetSpeculationPoisonRegister();
void set_builtin_index(int builtin_index) {
maybe_builtin_index_ = builtin_index;
}
protected:
static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
int smi_count = 0;
int heap_object_count = 0;
bool root_array_available_ = true;
int64_t RootRegisterDelta(ExternalReference other);
// Returns a register holding the smi value. The register MUST NOT be
// modified. It may be the "smi 1 constant" register.
Register GetSmiConstant(Smi* value);
// This handle will be patched with the code object on installation.
Handle<HeapObject> code_object_;
private:
int maybe_builtin_index_ = -1; // May be set while generating builtins.
bool has_frame_ = false;
Isolate* const isolate_ = nullptr;
};
// MacroAssembler implements a collection of frequently used macros.
......@@ -903,9 +884,6 @@ class MacroAssembler : public TurboAssembler {
void EnterBuiltinFrame(Register context, Register target, Register argc);
void LeaveBuiltinFrame(Register context, Register target, Register argc);
bool root_array_available() const { return root_array_available_; }
void set_root_array_available(bool v) { root_array_available_ = v; }
private:
// Order general registers are pushed by Pushad.
// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14, r15.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment