[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:
parent
ff0432c8b0
commit
c02a9fb179
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user