[ext-code-space] Allow AbstractCode to be CodeDataContainer

... when external code space is enabled.
Currently this mode is guarded by V8_REMOVE_BUILTINS_CODE_OBJECTS flag
which is set to false until Code-less builtins are supported.

Drive-by:
* remove unnecessary methods from AbstractCode,
* avoid CodeDataContainer <-> Code roundtrips when accessing writable
  state of Code objects via CodeT.

Bug: v8:11880
Change-Id: Iae3ff3b2feae68d875cbe9f82a6bb076460dd2f8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3769832
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81814}
This commit is contained in:
ishell@chromium.org 2022-07-19 14:53:13 +02:00 committed by V8 LUCI CQ
parent ff0432c8b0
commit c02a9fb179
7 changed files with 312 additions and 88 deletions

View File

@ -145,10 +145,15 @@ const size_t kShortBuiltinCallsOldSpaceSizeThreshold = size_t{2} * GB;
#ifdef V8_EXTERNAL_CODE_SPACE
#define V8_EXTERNAL_CODE_SPACE_BOOL true
// This flag enables the mode when V8 does not create trampoline Code objects
// for builtins. It should be enough to have only CodeDataContainer objects.
// TODO(v8:11880): remove the flag one the Code-less builtins mode works.
#define V8_REMOVE_BUILTINS_CODE_OBJECTS false
class CodeDataContainer;
using CodeT = CodeDataContainer;
#else
#define V8_EXTERNAL_CODE_SPACE_BOOL false
#define V8_REMOVE_BUILTINS_CODE_OBJECTS false
class Code;
using CodeT = Code;
#endif

View File

@ -47,111 +47,203 @@ CAST_ACCESSOR(DependentCode)
CAST_ACCESSOR(DeoptimizationData)
CAST_ACCESSOR(DeoptimizationLiteralArray)
int AbstractCode::raw_instruction_size(PtrComprCageBase cage_base) {
if (IsCode(cage_base)) {
return GetCode().raw_instruction_size();
} else {
return GetBytecodeArray().length();
}
}
int AbstractCode::InstructionSize(PtrComprCageBase cage_base) {
if (IsCode(cage_base)) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().InstructionSize();
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT().InstructionSize();
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return GetBytecodeArray().length();
}
}
ByteArray AbstractCode::SourcePositionTableInternal(
PtrComprCageBase cage_base) {
if (IsCode(cage_base)) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
DCHECK_NE(GetCode().kind(), CodeKind::BASELINE);
return GetCode().source_position_table(cage_base);
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
CodeT codet = GetCodeT();
if (codet.is_off_heap_trampoline()) {
return GetReadOnlyRoots().empty_byte_array();
}
return codet.source_position_table(cage_base);
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return GetBytecodeArray().SourcePositionTable(cage_base);
}
}
ByteArray AbstractCode::SourcePositionTable(PtrComprCageBase cage_base,
SharedFunctionInfo sfi) {
if (IsCode(cage_base)) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().SourcePositionTable(cage_base, sfi);
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
CodeT codet = GetCodeT();
if (codet.is_off_heap_trampoline()) {
return GetReadOnlyRoots().empty_byte_array();
}
return FromCodeT(codet).SourcePositionTable(cage_base, sfi);
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return GetBytecodeArray().SourcePositionTable(cage_base);
}
}
int AbstractCode::SizeIncludingMetadata(PtrComprCageBase cage_base) {
if (IsCode(cage_base)) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().SizeIncludingMetadata(cage_base);
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
CodeT codet = GetCodeT();
return codet.is_off_heap_trampoline()
? 0
: FromCodeT(codet).SizeIncludingMetadata(cage_base);
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return GetBytecodeArray().SizeIncludingMetadata();
}
}
Address AbstractCode::raw_instruction_start(PtrComprCageBase cage_base) {
if (IsCode(cage_base)) {
return GetCode().raw_instruction_start();
} else {
return GetBytecodeArray().GetFirstBytecodeAddress();
}
}
Address AbstractCode::InstructionStart(PtrComprCageBase cage_base) {
if (IsCode(cage_base)) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().InstructionStart();
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT().InstructionStart();
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return GetBytecodeArray().GetFirstBytecodeAddress();
}
}
Address AbstractCode::raw_instruction_end(PtrComprCageBase cage_base) {
if (IsCode(cage_base)) {
return GetCode().raw_instruction_end();
} else {
return GetBytecodeArray().GetFirstBytecodeAddress() +
GetBytecodeArray().length();
}
}
Address AbstractCode::InstructionEnd(PtrComprCageBase cage_base) {
if (IsCode(cage_base)) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().InstructionEnd();
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT().InstructionEnd();
} else {
return GetBytecodeArray().GetFirstBytecodeAddress() +
GetBytecodeArray().length();
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
BytecodeArray bytecode_array = GetBytecodeArray();
return bytecode_array.GetFirstBytecodeAddress() + bytecode_array.length();
}
}
bool AbstractCode::contains(Isolate* isolate, Address inner_pointer) {
PtrComprCageBase cage_base(isolate);
if (IsCode(cage_base)) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().contains(isolate, inner_pointer);
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT().contains(isolate, inner_pointer);
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return (address() <= inner_pointer) &&
(inner_pointer <= address() + Size(cage_base));
}
}
CodeKind AbstractCode::kind(PtrComprCageBase cage_base) {
return IsCode(cage_base) ? GetCode().kind() : CodeKind::INTERPRETED_FUNCTION;
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().kind();
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT().kind();
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return CodeKind::INTERPRETED_FUNCTION;
}
}
Builtin AbstractCode::builtin_id(PtrComprCageBase cage_base) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().builtin_id();
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT().builtin_id();
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return Builtin::kNoBuiltinId;
}
}
bool AbstractCode::is_interpreter_trampoline_builtin(
PtrComprCageBase cage_base) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().is_interpreter_trampoline_builtin();
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT().is_interpreter_trampoline_builtin();
} else {
DCHECK(InstanceTypeChecker::IsBytecodeArray(instance_type));
return false;
}
}
HandlerTable::CatchPrediction AbstractCode::GetBuiltinCatchPrediction(
PtrComprCageBase cage_base) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return GetCode().GetBuiltinCatchPrediction();
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT().GetBuiltinCatchPrediction();
} else {
UNREACHABLE();
}
}
bool AbstractCode::IsCode(PtrComprCageBase cage_base) const {
return HeapObject::IsCode(cage_base);
}
Code AbstractCode::GetCode() { return Code::cast(*this); }
bool AbstractCode::IsCodeT(PtrComprCageBase cage_base) const {
CHECK(V8_REMOVE_BUILTINS_CODE_OBJECTS);
return HeapObject::IsCodeT(cage_base);
}
bool AbstractCode::IsBytecodeArray(PtrComprCageBase cage_base) const {
return HeapObject::IsBytecodeArray(cage_base);
}
Code AbstractCode::GetCode() { return Code::cast(*this); }
CodeT AbstractCode::GetCodeT() {
CHECK(V8_REMOVE_BUILTINS_CODE_OBJECTS);
return CodeT::cast(*this);
}
BytecodeArray AbstractCode::GetBytecodeArray() {
return BytecodeArray::cast(*this);
}
CodeT AbstractCode::ToCodeT(PtrComprCageBase cage_base) {
InstanceType instance_type = map(cage_base).instance_type();
if (InstanceTypeChecker::IsCode(instance_type)) {
return i::ToCodeT(GetCode());
} else if (V8_REMOVE_BUILTINS_CODE_OBJECTS &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
return GetCodeT();
} else {
UNREACHABLE();
}
}
OBJECT_CONSTRUCTORS_IMPL(Code, HeapObject)
NEVER_READ_ONLY_SPACE_IMPL(Code)
@ -331,6 +423,9 @@ inline Handle<Code> FromCodeT(Handle<CodeT> code, Isolate* isolate) {
inline Handle<AbstractCode> ToAbstractCode(Handle<CodeT> code,
Isolate* isolate) {
if (V8_REMOVE_BUILTINS_CODE_OBJECTS) {
return Handle<AbstractCode>::cast(code);
}
return Handle<AbstractCode>::cast(FromCodeT(code, isolate));
}
@ -434,6 +529,14 @@ int Code::InstructionSize() const {
: raw_instruction_size();
}
#ifdef V8_EXTERNAL_CODE_SPACE
int CodeDataContainer::InstructionSize() const {
return V8_UNLIKELY(is_off_heap_trampoline())
? OffHeapInstructionSize(*this, builtin_id())
: code().raw_instruction_size();
}
#endif // V8_EXTERNAL_CODE_SPACE
Address Code::raw_instruction_start() const {
return field_address(kHeaderSize);
}
@ -454,6 +557,14 @@ Address Code::InstructionEnd() const {
: raw_instruction_end();
}
#ifdef V8_EXTERNAL_CODE_SPACE
Address CodeDataContainer::InstructionEnd() const {
return V8_UNLIKELY(is_off_heap_trampoline())
? i::OffHeapInstructionEnd(*this, builtin_id())
: code().raw_instruction_end();
}
#endif // V8_EXTERNAL_CODE_SPACE
Address Code::raw_metadata_start() const {
return raw_instruction_start() + raw_instruction_size();
}
@ -637,16 +748,26 @@ int Code::relocation_size() const {
Address Code::entry() const { return raw_instruction_start(); }
bool Code::contains(Isolate* isolate, Address inner_pointer) {
if (is_off_heap_trampoline()) {
if (OffHeapInstructionStart(isolate, inner_pointer) <= inner_pointer &&
inner_pointer < OffHeapInstructionEnd(isolate, inner_pointer)) {
return true;
}
if (is_off_heap_trampoline() &&
OffHeapBuiltinContains(isolate, inner_pointer)) {
return true;
}
return (address() <= inner_pointer) &&
(inner_pointer < address() + CodeSize());
}
#ifdef V8_EXTERNAL_CODE_SPACE
bool CodeDataContainer::contains(Isolate* isolate, Address inner_pointer) {
if (is_off_heap_trampoline() &&
OffHeapBuiltinContains(isolate, inner_pointer)) {
return true;
}
Code code = this->code();
return (code.address() <= inner_pointer) &&
(inner_pointer < code.address() + code.CodeSize());
}
#endif // V8_EXTERNAL_CODE_SPACE
// static
void Code::CopyRelocInfoToByteArray(ByteArray dest, const CodeDesc& desc) {
DCHECK_EQ(dest.length(), desc.reloc_size);
@ -799,34 +920,70 @@ inline bool CodeDataContainer::is_maglevved() const {
}
#endif
inline bool CodeDataContainer::can_have_weak_objects() const {
#ifdef V8_EXTERNAL_CODE_SPACE
// kind field is not available on CodeDataContainer when external code space
// is not enabled.
DCHECK(CodeKindIsOptimizedJSFunction(kind()));
#endif
int32_t flags = kind_specific_flags(kRelaxedLoad);
return Code::CanHaveWeakObjectsField::decode(flags);
}
inline void CodeDataContainer::set_can_have_weak_objects(bool value) {
#ifdef V8_EXTERNAL_CODE_SPACE
// kind field is not available on CodeDataContainer when external code space
// is not enabled.
DCHECK(CodeKindIsOptimizedJSFunction(kind()));
#endif
int32_t previous = kind_specific_flags(kRelaxedLoad);
int32_t updated = Code::CanHaveWeakObjectsField::update(previous, value);
set_kind_specific_flags(updated, kRelaxedStore);
}
inline bool Code::can_have_weak_objects() const {
DCHECK(CodeKindIsOptimizedJSFunction(kind()));
int32_t flags =
code_data_container(kAcquireLoad).kind_specific_flags(kRelaxedLoad);
return CanHaveWeakObjectsField::decode(flags);
CodeDataContainer container = code_data_container(kAcquireLoad);
return container.can_have_weak_objects();
}
inline void Code::set_can_have_weak_objects(bool value) {
DCHECK(CodeKindIsOptimizedJSFunction(kind()));
CodeDataContainer container = code_data_container(kAcquireLoad);
int32_t previous = container.kind_specific_flags(kRelaxedLoad);
int32_t updated = CanHaveWeakObjectsField::update(previous, value);
container.set_kind_specific_flags(updated, kRelaxedStore);
container.set_can_have_weak_objects(value);
}
inline bool CodeDataContainer::is_promise_rejection() const {
#ifdef V8_EXTERNAL_CODE_SPACE
// kind field is not available on CodeDataContainer when external code space
// is not enabled.
DCHECK_EQ(kind(), CodeKind::BUILTIN);
#endif
int32_t flags = kind_specific_flags(kRelaxedLoad);
return Code::IsPromiseRejectionField::decode(flags);
}
inline void CodeDataContainer::set_is_promise_rejection(bool value) {
#ifdef V8_EXTERNAL_CODE_SPACE
// kind field is not available on CodeDataContainer when external code space
// is not enabled.
DCHECK_EQ(kind(), CodeKind::BUILTIN);
#endif
int32_t previous = kind_specific_flags(kRelaxedLoad);
int32_t updated = Code::IsPromiseRejectionField::update(previous, value);
set_kind_specific_flags(updated, kRelaxedStore);
}
inline bool Code::is_promise_rejection() const {
DCHECK(kind() == CodeKind::BUILTIN);
int32_t flags =
code_data_container(kAcquireLoad).kind_specific_flags(kRelaxedLoad);
return IsPromiseRejectionField::decode(flags);
DCHECK_EQ(kind(), CodeKind::BUILTIN);
CodeDataContainer container = code_data_container(kAcquireLoad);
return container.is_promise_rejection();
}
inline void Code::set_is_promise_rejection(bool value) {
DCHECK(kind() == CodeKind::BUILTIN);
DCHECK_EQ(kind(), CodeKind::BUILTIN);
CodeDataContainer container = code_data_container(kAcquireLoad);
int32_t previous = container.kind_specific_flags(kRelaxedLoad);
int32_t updated = IsPromiseRejectionField::update(previous, value);
container.set_kind_specific_flags(updated, kRelaxedStore);
container.set_is_promise_rejection(value);
}
inline bool Code::is_off_heap_trampoline() const {
@ -834,7 +991,13 @@ inline bool Code::is_off_heap_trampoline() const {
return IsOffHeapTrampoline::decode(flags);
}
inline HandlerTable::CatchPrediction Code::GetBuiltinCatchPrediction() {
inline HandlerTable::CatchPrediction Code::GetBuiltinCatchPrediction() const {
if (is_promise_rejection()) return HandlerTable::PROMISE;
return HandlerTable::UNCAUGHT;
}
inline HandlerTable::CatchPrediction
CodeDataContainer::GetBuiltinCatchPrediction() const {
if (is_promise_rejection()) return HandlerTable::PROMISE;
return HandlerTable::UNCAUGHT;
}

View File

@ -250,8 +250,7 @@ Address CodeDataContainer::OffHeapInstructionStart(Isolate* isolate,
Address Code::OffHeapInstructionEnd(Isolate* isolate, Address pc) const {
DCHECK(is_off_heap_trampoline());
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
return d.InstructionStartOfBuiltin(builtin_id()) +
d.InstructionSizeOfBuiltin(builtin_id());
return d.InstructionEndOf(builtin_id());
}
#ifdef V8_EXTERNAL_CODE_SPACE
@ -259,10 +258,24 @@ Address CodeDataContainer::OffHeapInstructionEnd(Isolate* isolate,
Address pc) const {
DCHECK(is_off_heap_trampoline());
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
return d.InstructionStartOfBuiltin(builtin_id()) +
d.InstructionSizeOfBuiltin(builtin_id());
return d.InstructionEndOf(builtin_id());
}
#endif
#endif // V8_EXTERNAL_CODE_SPACE
bool Code::OffHeapBuiltinContains(Isolate* isolate, Address pc) const {
DCHECK(is_off_heap_trampoline());
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
return d.BuiltinContains(builtin_id(), pc);
}
#ifdef V8_EXTERNAL_CODE_SPACE
bool CodeDataContainer::OffHeapBuiltinContains(Isolate* isolate,
Address pc) const {
DCHECK(is_off_heap_trampoline());
EmbeddedData d = EmbeddedData::GetEmbeddedDataForPC(isolate, pc);
return d.BuiltinContains(builtin_id(), pc);
}
#endif // V8_EXTERNAL_CODE_SPACE
// TODO(cbruni): Move to BytecodeArray
int AbstractCode::SourcePosition(PtrComprCageBase cage_base, int offset) {

View File

@ -60,11 +60,11 @@ class CodeDataContainer : public HeapObject {
// writable state of the respective Code object.
//
inline bool can_have_weak_objects() const;
inline void set_can_have_weak_objects(bool value);
DECL_PRIMITIVE_ACCESSORS(can_have_weak_objects, bool)
DECL_PRIMITIVE_ACCESSORS(marked_for_deoptimization, bool)
DECL_PRIMITIVE_ACCESSORS(is_promise_rejection, bool)
inline bool marked_for_deoptimization() const;
inline void set_marked_for_deoptimization(bool flag);
inline HandlerTable::CatchPrediction GetBuiltinCatchPrediction() const;
// Back-reference to the Code object.
// Available only when V8_EXTERNAL_CODE_SPACE is defined.
@ -165,6 +165,9 @@ class CodeDataContainer : public HeapObject {
DECL_GETTER(source_position_table, ByteArray)
DECL_GETTER(bytecode_offset_table, ByteArray)
// Returns true if pc is inside this object's instructions.
inline bool contains(Isolate* isolate, Address pc);
inline Address SafepointTableAddress() const;
inline int safepoint_table_size() const;
inline bool has_safepoint_table() const;
@ -190,10 +193,14 @@ class CodeDataContainer : public HeapObject {
// TODO(11527): remove these versions once the full solution is ready.
Address OffHeapInstructionStart(Isolate* isolate, Address pc) const;
Address OffHeapInstructionEnd(Isolate* isolate, Address pc) const;
bool OffHeapBuiltinContains(Isolate* isolate, Address pc) const;
inline Address InstructionStart(Isolate* isolate, Address pc) const;
inline Address InstructionEnd(Isolate* isolate, Address pc) const;
inline Address InstructionEnd() const;
inline int InstructionSize() const;
#endif // V8_EXTERNAL_CODE_SPACE
DECL_CAST(CodeDataContainer)
@ -353,6 +360,9 @@ class Code : public HeapObject {
V8_EXPORT_PRIVATE Address OffHeapInstructionEnd(Isolate* isolate,
Address pc) const;
V8_EXPORT_PRIVATE bool OffHeapBuiltinContains(Isolate* isolate,
Address pc) const;
// Computes offset of the |pc| from the instruction start. The |pc| must
// belong to this code.
inline int GetOffsetFromInstructionStart(Isolate* isolate, Address pc) const;
@ -638,7 +648,7 @@ class Code : public HeapObject {
void SetMarkedForDeoptimization(const char* reason);
inline HandlerTable::CatchPrediction GetBuiltinCatchPrediction();
inline HandlerTable::CatchPrediction GetBuiltinCatchPrediction() const;
bool IsIsolateIndependent(Isolate* isolate);
@ -944,6 +954,12 @@ inline Code FromCodeT(CodeT code, PtrComprCageBase, AcquireLoadTag);
inline Handle<CodeT> FromCodeT(Handle<Code> code, Isolate* isolate);
inline CodeDataContainer CodeDataContainerFromCodeT(CodeT code);
// AbsractCode is an helper wrapper around {Code | BytecodeArray} or
// {Code | CodeDataContainer | BytecodeArray} depending on whether the
// V8_REMOVE_BUILTINS_CODE_OBJECTS is disabled or not.
// Note that when V8_EXTERNAL_CODE_SPACE is enabled then the same abstract code
// can be represented either by Code object or by respective CodeDataContainer
// object.
class AbstractCode : public HeapObject {
public:
NEVER_READ_ONLY_SPACE
@ -951,25 +967,16 @@ class AbstractCode : public HeapObject {
int SourcePosition(PtrComprCageBase cage_base, int offset);
int SourceStatementPosition(PtrComprCageBase cage_base, int offset);
// Returns the address of the first instruction.
inline Address raw_instruction_start(PtrComprCageBase cage_base);
// Returns the address of the first instruction. For off-heap code objects
// this differs from instruction_start (which would point to the off-heap
// trampoline instead).
inline Address InstructionStart(PtrComprCageBase cage_base);
// Returns the address right after the last instruction.
inline Address raw_instruction_end(PtrComprCageBase cage_base);
// Returns the address right after the last instruction. For off-heap code
// objects this differs from instruction_end (which would point to the
// off-heap trampoline instead).
inline Address InstructionEnd(PtrComprCageBase cage_base);
// Returns the size of the code instructions.
inline int raw_instruction_size(PtrComprCageBase cage_base);
// Returns the size of the native instructions, including embedded
// data such as the safepoints table. For off-heap code objects
// this may differ from instruction_size in that this will return the size of
@ -992,12 +999,27 @@ class AbstractCode : public HeapObject {
// Returns the kind of the code.
inline CodeKind kind(PtrComprCageBase cage_base);
inline Builtin builtin_id(PtrComprCageBase cage_base);
inline bool is_interpreter_trampoline_builtin(PtrComprCageBase cage_base);
inline HandlerTable::CatchPrediction GetBuiltinCatchPrediction(
PtrComprCageBase cage_base);
DECL_CAST(AbstractCode)
// The following predicates don't have the parameterless versions on
// purpose - in order to avoid the expensive cage base computation that
// should work for both regular V8 heap objects and external code space
// objects.
inline bool IsCode(PtrComprCageBase cage_base) const;
inline Code GetCode();
inline bool IsCodeT(PtrComprCageBase cage_base) const;
inline bool IsBytecodeArray(PtrComprCageBase cage_base) const;
inline CodeT ToCodeT(PtrComprCageBase cage_base);
inline Code GetCode();
inline CodeT GetCodeT();
inline BytecodeArray GetBytecodeArray();
OBJECT_CONSTRUCTORS(AbstractCode, HeapObject);

View File

@ -10,6 +10,17 @@
namespace v8 {
namespace internal {
bool EmbeddedData::BuiltinContains(Builtin builtin, Address pc) const {
DCHECK(Builtins::IsBuiltinId(builtin));
const struct LayoutDescription& desc = LayoutDescription(builtin);
Address start =
reinterpret_cast<Address>(RawCode() + desc.instruction_offset);
DCHECK_LT(start, reinterpret_cast<Address>(code_ + code_size_));
if (pc < start) return false;
Address end = start + desc.instruction_length;
return pc < end;
}
Address EmbeddedData::InstructionStartOfBuiltin(Builtin builtin) const {
DCHECK(Builtins::IsBuiltinId(builtin));
const struct LayoutDescription& desc = LayoutDescription(builtin);
@ -18,6 +29,15 @@ Address EmbeddedData::InstructionStartOfBuiltin(Builtin builtin) const {
return reinterpret_cast<Address>(result);
}
Address EmbeddedData::InstructionEndOf(Builtin builtin) const {
DCHECK(Builtins::IsBuiltinId(builtin));
const struct LayoutDescription& desc = LayoutDescription(builtin);
const uint8_t* result =
RawCode() + desc.instruction_offset + desc.instruction_length;
DCHECK_LT(result, code_ + code_size_);
return reinterpret_cast<Address>(result);
}
uint32_t EmbeddedData::InstructionSizeOfBuiltin(Builtin builtin) const {
DCHECK(Builtins::IsBuiltinId(builtin));
const struct LayoutDescription& desc = LayoutDescription(builtin);

View File

@ -127,8 +127,11 @@ class EmbeddedData final {
data_ = nullptr;
}
inline bool BuiltinContains(Builtin builtin, Address pc) const;
// TODO(ishell): rename XyzOfBuiltin() to XyzOf().
inline Address InstructionStartOfBuiltin(Builtin builtin) const;
inline Address InstructionEndOf(Builtin builtin) const;
inline uint32_t InstructionSizeOfBuiltin(Builtin builtin) const;
inline Address InstructionStartOfBytecodeHandlers() const;

View File

@ -264,17 +264,15 @@ TEST(TickEvents) {
frame3_code, "ddd");
PtrComprCageBase cage_base(isolate);
EnqueueTickSampleEvent(processor, frame1_code->InstructionStart(cage_base));
EnqueueTickSampleEvent(processor,
frame1_code->raw_instruction_start(cage_base));
EnqueueTickSampleEvent(processor,
frame2_code->raw_instruction_start(cage_base) +
frame2_code->raw_instruction_size(cage_base) / 2,
frame1_code->raw_instruction_start(cage_base) +
frame1_code->raw_instruction_size(cage_base) / 2);
EnqueueTickSampleEvent(processor,
frame3_code->raw_instruction_end(cage_base) - 1,
frame2_code->raw_instruction_end(cage_base) - 1,
frame1_code->raw_instruction_end(cage_base) - 1);
frame2_code->InstructionStart(cage_base) +
frame2_code->InstructionSize(cage_base) / 2,
frame1_code->InstructionStart(cage_base) +
frame1_code->InstructionSize(cage_base) / 2);
EnqueueTickSampleEvent(processor, frame3_code->InstructionEnd(cage_base) - 1,
frame2_code->InstructionEnd(cage_base) - 1,
frame1_code->InstructionEnd(cage_base) - 1);
isolate->v8_file_logger()->RemoveLogEventListener(&profiler_listener);
processor->StopSynchronously();
@ -1290,7 +1288,7 @@ static void TickLines(bool optimize) {
!CcTest::i_isolate()->use_optimizer());
i::Handle<i::AbstractCode> code(func->abstract_code(isolate), isolate);
CHECK(!code->is_null());
i::Address code_address = code->raw_instruction_start(isolate);
i::Address code_address = code->InstructionStart(isolate);
CHECK_NE(code_address, kNullAddress);
CodeEntryStorage storage;