[compiler] Remove delayed string constants
StringConstantXXX were introduced when we switched to concurrent compilation, as a way to build strings in Turbofan in a background thread, without having to actually allocate them on the main heap from the background. See https://crrev.com/c/1221807. Now that we have local heaps, we can actually allocate strings from the background, making StringConstantXXX useless. Moreover, we would fold constant string concatenations into ConsString, which sounds a bit dubious for performance. Now, small constant string concatenations will be folded into SeqStrings, while larger ones will remain ConsString, just to avoid the quadratic worst-case. Change-Id: I0479d16aa5691c9d774187c4cc0d03ff4fe2b4f9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3811291 Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Darius Mercadier <dmercadier@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#82381}
This commit is contained in:
parent
aff4d490ce
commit
de04959f17
@ -1222,8 +1222,6 @@ filegroup(
|
||||
"src/codegen/source-position-table.h",
|
||||
"src/codegen/source-position.cc",
|
||||
"src/codegen/source-position.h",
|
||||
"src/codegen/string-constants.cc",
|
||||
"src/codegen/string-constants.h",
|
||||
"src/codegen/tick-counter.cc",
|
||||
"src/codegen/tick-counter.h",
|
||||
"src/codegen/tnode.cc",
|
||||
|
2
BUILD.gn
2
BUILD.gn
@ -2849,7 +2849,6 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/signature.h",
|
||||
"src/codegen/source-position-table.h",
|
||||
"src/codegen/source-position.h",
|
||||
"src/codegen/string-constants.h",
|
||||
"src/codegen/tick-counter.h",
|
||||
"src/codegen/tnode.h",
|
||||
"src/codegen/turbo-assembler.h",
|
||||
@ -4416,7 +4415,6 @@ v8_source_set("v8_base_without_compiler") {
|
||||
"src/codegen/safepoint-table.cc",
|
||||
"src/codegen/source-position-table.cc",
|
||||
"src/codegen/source-position.cc",
|
||||
"src/codegen/string-constants.cc",
|
||||
"src/codegen/tick-counter.cc",
|
||||
"src/codegen/tnode.cc",
|
||||
"src/codegen/turbo-assembler.cc",
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "src/codegen/assembler-inl.h"
|
||||
#include "src/codegen/machine-type.h"
|
||||
#include "src/codegen/macro-assembler.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
|
||||
@ -398,15 +397,8 @@ Operand Operand::EmbeddedNumber(double value) {
|
||||
int32_t smi;
|
||||
if (DoubleToSmiInteger(value, &smi)) return Operand(Smi::FromInt(smi));
|
||||
Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
|
||||
result.is_heap_object_request_ = true;
|
||||
result.value_.heap_object_request = HeapObjectRequest(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
Operand Operand::EmbeddedStringConstant(const StringConstantBase* str) {
|
||||
Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
|
||||
result.is_heap_object_request_ = true;
|
||||
result.value_.heap_object_request = HeapObjectRequest(str);
|
||||
result.is_heap_number_request_ = true;
|
||||
result.value_.heap_number_request = HeapNumberRequest(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -463,22 +455,12 @@ void NeonMemOperand::SetAlignment(int align) {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
||||
DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty());
|
||||
for (auto& request : heap_object_requests_) {
|
||||
Handle<HeapObject> object;
|
||||
switch (request.kind()) {
|
||||
case HeapObjectRequest::kHeapNumber:
|
||||
object = isolate->factory()->NewHeapNumber<AllocationType::kOld>(
|
||||
void Assembler::AllocateAndInstallRequestedHeapNumbers(Isolate* isolate) {
|
||||
DCHECK_IMPLIES(isolate == nullptr, heap_number_requests_.empty());
|
||||
for (auto& request : heap_number_requests_) {
|
||||
Handle<HeapObject> object =
|
||||
isolate->factory()->NewHeapNumber<AllocationType::kOld>(
|
||||
request.heap_number());
|
||||
break;
|
||||
case HeapObjectRequest::kStringConstant: {
|
||||
const StringConstantBase* str = request.string();
|
||||
CHECK_NOT_NULL(str);
|
||||
object = str->AllocateStringConstant(isolate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
|
||||
Memory<Address>(constant_pool_entry_address(pc, 0 /* unused */)) =
|
||||
object.address();
|
||||
@ -585,7 +567,7 @@ void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
|
||||
|
||||
int code_comments_size = WriteCodeComments();
|
||||
|
||||
AllocateAndInstallRequestedHeapObjects(isolate);
|
||||
AllocateAndInstallRequestedHeapNumbers(isolate);
|
||||
|
||||
// Set up code descriptor.
|
||||
// TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
|
||||
@ -1214,8 +1196,8 @@ void Assembler::Move32BitImmediate(Register rd, const Operand& x,
|
||||
}
|
||||
} else {
|
||||
int32_t immediate;
|
||||
if (x.IsHeapObjectRequest()) {
|
||||
RequestHeapObject(x.heap_object_request());
|
||||
if (x.IsHeapNumberRequest()) {
|
||||
RequestHeapNumber(x.heap_number_request());
|
||||
immediate = 0;
|
||||
} else {
|
||||
immediate = x.immediate();
|
||||
|
@ -116,7 +116,6 @@ class V8_EXPORT_PRIVATE Operand {
|
||||
explicit Operand(Register rm, ShiftOp shift_op, Register rs);
|
||||
|
||||
static Operand EmbeddedNumber(double number); // Smi or HeapNumber.
|
||||
static Operand EmbeddedStringConstant(const StringConstantBase* str);
|
||||
|
||||
// Return true if this is a register operand.
|
||||
bool IsRegister() const {
|
||||
@ -148,21 +147,21 @@ class V8_EXPORT_PRIVATE Operand {
|
||||
|
||||
inline int32_t immediate() const {
|
||||
DCHECK(IsImmediate());
|
||||
DCHECK(!IsHeapObjectRequest());
|
||||
DCHECK(!IsHeapNumberRequest());
|
||||
return value_.immediate;
|
||||
}
|
||||
bool IsImmediate() const { return !rm_.is_valid(); }
|
||||
|
||||
HeapObjectRequest heap_object_request() const {
|
||||
DCHECK(IsHeapObjectRequest());
|
||||
return value_.heap_object_request;
|
||||
HeapNumberRequest heap_number_request() const {
|
||||
DCHECK(IsHeapNumberRequest());
|
||||
return value_.heap_number_request;
|
||||
}
|
||||
bool IsHeapObjectRequest() const {
|
||||
DCHECK_IMPLIES(is_heap_object_request_, IsImmediate());
|
||||
DCHECK_IMPLIES(is_heap_object_request_,
|
||||
bool IsHeapNumberRequest() const {
|
||||
DCHECK_IMPLIES(is_heap_number_request_, IsImmediate());
|
||||
DCHECK_IMPLIES(is_heap_number_request_,
|
||||
rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
|
||||
rmode_ == RelocInfo::CODE_TARGET);
|
||||
return is_heap_object_request_;
|
||||
return is_heap_number_request_;
|
||||
}
|
||||
|
||||
Register rm() const { return rm_; }
|
||||
@ -176,10 +175,10 @@ class V8_EXPORT_PRIVATE Operand {
|
||||
int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
|
||||
union Value {
|
||||
Value() {}
|
||||
HeapObjectRequest heap_object_request; // if is_heap_object_request_
|
||||
HeapNumberRequest heap_number_request; // if is_heap_number_request_
|
||||
int32_t immediate; // otherwise
|
||||
} value_; // valid if rm_ == no_reg
|
||||
bool is_heap_object_request_ = false;
|
||||
bool is_heap_number_request_ = false;
|
||||
RelocInfo::Mode rmode_;
|
||||
|
||||
friend class Assembler;
|
||||
@ -1344,7 +1343,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
|
||||
void ConstantPoolAddEntry(int position, RelocInfo::Mode rmode,
|
||||
intptr_t value);
|
||||
void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
|
||||
void AllocateAndInstallRequestedHeapNumbers(Isolate* isolate);
|
||||
|
||||
int WriteCodeComments();
|
||||
|
||||
|
@ -268,21 +268,21 @@ Operand::Operand(Register reg, Extend extend, unsigned shift_amount)
|
||||
DCHECK(reg.Is64Bits() || ((extend != SXTX) && (extend != UXTX)));
|
||||
}
|
||||
|
||||
bool Operand::IsHeapObjectRequest() const {
|
||||
DCHECK_IMPLIES(heap_object_request_.has_value(), reg_ == NoReg);
|
||||
DCHECK_IMPLIES(heap_object_request_.has_value(),
|
||||
bool Operand::IsHeapNumberRequest() const {
|
||||
DCHECK_IMPLIES(heap_number_request_.has_value(), reg_ == NoReg);
|
||||
DCHECK_IMPLIES(heap_number_request_.has_value(),
|
||||
immediate_.rmode() == RelocInfo::FULL_EMBEDDED_OBJECT ||
|
||||
immediate_.rmode() == RelocInfo::CODE_TARGET);
|
||||
return heap_object_request_.has_value();
|
||||
return heap_number_request_.has_value();
|
||||
}
|
||||
|
||||
HeapObjectRequest Operand::heap_object_request() const {
|
||||
DCHECK(IsHeapObjectRequest());
|
||||
return *heap_object_request_;
|
||||
HeapNumberRequest Operand::heap_number_request() const {
|
||||
DCHECK(IsHeapNumberRequest());
|
||||
return *heap_number_request_;
|
||||
}
|
||||
|
||||
bool Operand::IsImmediate() const {
|
||||
return reg_ == NoReg && !IsHeapObjectRequest();
|
||||
return reg_ == NoReg && !IsHeapNumberRequest();
|
||||
}
|
||||
|
||||
bool Operand::IsShiftedRegister() const {
|
||||
@ -319,11 +319,8 @@ Operand Operand::ToW() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Immediate Operand::immediate_for_heap_object_request() const {
|
||||
DCHECK((heap_object_request().kind() == HeapObjectRequest::kHeapNumber &&
|
||||
immediate_.rmode() == RelocInfo::FULL_EMBEDDED_OBJECT) ||
|
||||
(heap_object_request().kind() == HeapObjectRequest::kStringConstant &&
|
||||
immediate_.rmode() == RelocInfo::FULL_EMBEDDED_OBJECT));
|
||||
Immediate Operand::immediate_for_heap_number_request() const {
|
||||
DCHECK(immediate_.rmode() == RelocInfo::FULL_EMBEDDED_OBJECT);
|
||||
return immediate_;
|
||||
}
|
||||
|
||||
@ -338,7 +335,7 @@ int64_t Operand::ImmediateValue() const {
|
||||
}
|
||||
|
||||
RelocInfo::Mode Operand::ImmediateRMode() const {
|
||||
DCHECK(IsImmediate() || IsHeapObjectRequest());
|
||||
DCHECK(IsImmediate() || IsHeapNumberRequest());
|
||||
return immediate_.rmode();
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "src/codegen/arm64/assembler-arm64-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/safepoint-table.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/execution/frame-constants.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -362,28 +361,15 @@ win64_unwindinfo::BuiltinUnwindInfo Assembler::GetUnwindInfo() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
||||
DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty());
|
||||
for (auto& request : heap_object_requests_) {
|
||||
void Assembler::AllocateAndInstallRequestedHeapNumbers(Isolate* isolate) {
|
||||
DCHECK_IMPLIES(isolate == nullptr, heap_number_requests_.empty());
|
||||
for (auto& request : heap_number_requests_) {
|
||||
Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
|
||||
switch (request.kind()) {
|
||||
case HeapObjectRequest::kHeapNumber: {
|
||||
Handle<HeapObject> object =
|
||||
isolate->factory()->NewHeapNumber<AllocationType::kOld>(
|
||||
request.heap_number());
|
||||
EmbeddedObjectIndex index = AddEmbeddedObject(object);
|
||||
set_embedded_object_index_referenced_from(pc, index);
|
||||
break;
|
||||
}
|
||||
case HeapObjectRequest::kStringConstant: {
|
||||
const StringConstantBase* str = request.string();
|
||||
CHECK_NOT_NULL(str);
|
||||
EmbeddedObjectIndex index =
|
||||
AddEmbeddedObject(str->AllocateStringConstant(isolate));
|
||||
set_embedded_object_index_referenced_from(pc, index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Handle<HeapObject> object =
|
||||
isolate->factory()->NewHeapNumber<AllocationType::kOld>(
|
||||
request.heap_number());
|
||||
EmbeddedObjectIndex index = AddEmbeddedObject(object);
|
||||
set_embedded_object_index_referenced_from(pc, index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,7 +391,7 @@ void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
|
||||
|
||||
int code_comments_size = WriteCodeComments();
|
||||
|
||||
AllocateAndInstallRequestedHeapObjects(isolate);
|
||||
AllocateAndInstallRequestedHeapNumbers(isolate);
|
||||
|
||||
// Set up code descriptor.
|
||||
// TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
|
||||
@ -1321,23 +1307,16 @@ Operand Operand::EmbeddedNumber(double number) {
|
||||
return Operand(Immediate(Smi::FromInt(smi)));
|
||||
}
|
||||
Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
|
||||
result.heap_object_request_.emplace(number);
|
||||
DCHECK(result.IsHeapObjectRequest());
|
||||
return result;
|
||||
}
|
||||
|
||||
Operand Operand::EmbeddedStringConstant(const StringConstantBase* str) {
|
||||
Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
|
||||
result.heap_object_request_.emplace(str);
|
||||
DCHECK(result.IsHeapObjectRequest());
|
||||
result.heap_number_request_.emplace(number);
|
||||
DCHECK(result.IsHeapNumberRequest());
|
||||
return result;
|
||||
}
|
||||
|
||||
void Assembler::ldr(const CPURegister& rt, const Operand& operand) {
|
||||
if (operand.IsHeapObjectRequest()) {
|
||||
BlockPoolsScope no_pool_before_ldr_of_heap_object_request(this);
|
||||
RequestHeapObject(operand.heap_object_request());
|
||||
ldr(rt, operand.immediate_for_heap_object_request());
|
||||
if (operand.IsHeapNumberRequest()) {
|
||||
BlockPoolsScope no_pool_before_ldr_of_heap_number_request(this);
|
||||
RequestHeapNumber(operand.heap_number_request());
|
||||
ldr(rt, operand.immediate_for_heap_number_request());
|
||||
} else {
|
||||
ldr(rt, operand.immediate());
|
||||
}
|
||||
@ -4392,9 +4371,9 @@ void Assembler::near_call(int offset, RelocInfo::Mode rmode) {
|
||||
bl(offset);
|
||||
}
|
||||
|
||||
void Assembler::near_call(HeapObjectRequest request) {
|
||||
void Assembler::near_call(HeapNumberRequest request) {
|
||||
BlockPoolsScope no_pool_before_bl_instr(this);
|
||||
RequestHeapObject(request);
|
||||
RequestHeapNumber(request);
|
||||
EmbeddedObjectIndex index = AddEmbeddedObject(Handle<CodeT>());
|
||||
RecordRelocInfo(RelocInfo::CODE_TARGET, index, NO_POOL_ENTRY);
|
||||
DCHECK(is_int32(index));
|
||||
|
@ -82,11 +82,10 @@ class Operand {
|
||||
inline Operand(Register reg, Extend extend, unsigned shift_amount = 0);
|
||||
|
||||
static Operand EmbeddedNumber(double number); // Smi or HeapNumber.
|
||||
static Operand EmbeddedStringConstant(const StringConstantBase* str);
|
||||
|
||||
inline bool IsHeapObjectRequest() const;
|
||||
inline HeapObjectRequest heap_object_request() const;
|
||||
inline Immediate immediate_for_heap_object_request() const;
|
||||
inline bool IsHeapNumberRequest() const;
|
||||
inline HeapNumberRequest heap_number_request() const;
|
||||
inline Immediate immediate_for_heap_number_request() const;
|
||||
|
||||
// Implicit constructor for all int types, ExternalReference, and Smi.
|
||||
template <typename T>
|
||||
@ -120,7 +119,7 @@ class Operand {
|
||||
bool NeedsRelocation(const Assembler* assembler) const;
|
||||
|
||||
private:
|
||||
base::Optional<HeapObjectRequest> heap_object_request_;
|
||||
base::Optional<HeapNumberRequest> heap_number_request_;
|
||||
Immediate immediate_;
|
||||
Register reg_;
|
||||
Shift shift_;
|
||||
@ -239,8 +238,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// instruction.
|
||||
void near_call(int offset, RelocInfo::Mode rmode);
|
||||
// Generate a BL immediate instruction with the corresponding relocation info
|
||||
// for the input HeapObjectRequest.
|
||||
void near_call(HeapObjectRequest request);
|
||||
// for the input HeapNumberRequest.
|
||||
void near_call(HeapNumberRequest request);
|
||||
|
||||
// Return the address in the constant pool of the code target address used by
|
||||
// the branch/call instruction at pc.
|
||||
@ -2757,7 +2756,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// the length of the label chain.
|
||||
void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label);
|
||||
|
||||
void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
|
||||
void AllocateAndInstallRequestedHeapNumbers(Isolate* isolate);
|
||||
|
||||
int WriteCodeComments();
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#endif
|
||||
#include "src/base/vector.h"
|
||||
#include "src/codegen/assembler-inl.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/diagnostics/disassembler.h"
|
||||
#include "src/execution/isolate.h"
|
||||
@ -230,17 +229,10 @@ unsigned CpuFeatures::supported_ = 0;
|
||||
unsigned CpuFeatures::icache_line_size_ = 0;
|
||||
unsigned CpuFeatures::dcache_line_size_ = 0;
|
||||
|
||||
HeapObjectRequest::HeapObjectRequest(double heap_number, int offset)
|
||||
: kind_(kHeapNumber), offset_(offset) {
|
||||
value_.heap_number = heap_number;
|
||||
DCHECK(!IsSmiDouble(value_.heap_number));
|
||||
}
|
||||
|
||||
HeapObjectRequest::HeapObjectRequest(const StringConstantBase* string,
|
||||
int offset)
|
||||
: kind_(kStringConstant), offset_(offset) {
|
||||
value_.string = string;
|
||||
DCHECK_NOT_NULL(value_.string);
|
||||
HeapNumberRequest::HeapNumberRequest(double heap_number, int offset)
|
||||
: offset_(offset) {
|
||||
value_ = heap_number;
|
||||
DCHECK(!IsSmiDouble(value_));
|
||||
}
|
||||
|
||||
// Platform specific but identical code for all the platforms.
|
||||
@ -267,9 +259,9 @@ void Assembler::DataAlign(int m) {
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblerBase::RequestHeapObject(HeapObjectRequest request) {
|
||||
void AssemblerBase::RequestHeapNumber(HeapNumberRequest request) {
|
||||
request.set_offset(pc_offset());
|
||||
heap_object_requests_.push_front(request);
|
||||
heap_number_requests_.push_front(request);
|
||||
}
|
||||
|
||||
int AssemblerBase::AddCodeTarget(Handle<CodeT> target) {
|
||||
|
@ -70,7 +70,6 @@ class Isolate;
|
||||
class SCTableReference;
|
||||
class SourcePosition;
|
||||
class StatsCounter;
|
||||
class StringConstantBase;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Optimization for far-jmp like instructions that can be replaced by shorter.
|
||||
@ -103,23 +102,11 @@ class JumpOptimizationInfo {
|
||||
size_t hash_code_ = 0u;
|
||||
};
|
||||
|
||||
class HeapObjectRequest {
|
||||
class HeapNumberRequest {
|
||||
public:
|
||||
explicit HeapObjectRequest(double heap_number, int offset = -1);
|
||||
explicit HeapObjectRequest(const StringConstantBase* string, int offset = -1);
|
||||
explicit HeapNumberRequest(double heap_number, int offset = -1);
|
||||
|
||||
enum Kind { kHeapNumber, kStringConstant };
|
||||
Kind kind() const { return kind_; }
|
||||
|
||||
double heap_number() const {
|
||||
DCHECK_EQ(kind(), kHeapNumber);
|
||||
return value_.heap_number;
|
||||
}
|
||||
|
||||
const StringConstantBase* string() const {
|
||||
DCHECK_EQ(kind(), kStringConstant);
|
||||
return value_.string;
|
||||
}
|
||||
double heap_number() const { return value_; }
|
||||
|
||||
// The code buffer offset at the time of the request.
|
||||
int offset() const {
|
||||
@ -133,13 +120,7 @@ class HeapObjectRequest {
|
||||
}
|
||||
|
||||
private:
|
||||
Kind kind_;
|
||||
|
||||
union {
|
||||
double heap_number;
|
||||
const StringConstantBase* string;
|
||||
} value_;
|
||||
|
||||
double value_;
|
||||
int offset_;
|
||||
};
|
||||
|
||||
@ -388,7 +369,7 @@ class V8_EXPORT_PRIVATE AssemblerBase : public Malloced {
|
||||
std::unique_ptr<AssemblerBuffer> buffer_;
|
||||
// Cached from {buffer_->start()}, for faster access.
|
||||
byte* buffer_start_;
|
||||
std::forward_list<HeapObjectRequest> heap_object_requests_;
|
||||
std::forward_list<HeapNumberRequest> heap_number_requests_;
|
||||
// The program counter, which points into the buffer above and moves forward.
|
||||
// TODO(jkummerow): This should probably have type {Address}.
|
||||
byte* pc_;
|
||||
@ -402,12 +383,12 @@ class V8_EXPORT_PRIVATE AssemblerBase : public Malloced {
|
||||
}
|
||||
}
|
||||
|
||||
// {RequestHeapObject} records the need for a future heap number allocation,
|
||||
// {RequestHeapNumber} records the need for a future heap number allocation,
|
||||
// code stub generation or string allocation. After code assembly, each
|
||||
// platform's {Assembler::AllocateAndInstallRequestedHeapObjects} will
|
||||
// platform's {Assembler::AllocateAndInstallRequestedHeapNumbers} will
|
||||
// allocate these objects and place them where they are expected (determined
|
||||
// by the pc offset associated with each request).
|
||||
void RequestHeapObject(HeapObjectRequest request);
|
||||
void RequestHeapNumber(HeapNumberRequest request);
|
||||
|
||||
bool ShouldRecordRelocInfo(RelocInfo::Mode rmode) const {
|
||||
DCHECK(!RelocInfo::IsNoInfo(rmode));
|
||||
|
@ -120,8 +120,6 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
|
||||
V(ShadowRealmImportValueFulfilledSFI, \
|
||||
shadow_realm_import_value_fulfilled_sfi, \
|
||||
ShadowRealmImportValueFulfilledSFI) \
|
||||
V(SingleCharacterStringTable, single_character_string_table, \
|
||||
SingleCharacterStringTable) \
|
||||
V(StringIteratorProtector, string_iterator_protector, \
|
||||
StringIteratorProtector) \
|
||||
V(TypedArraySpeciesProtector, typed_array_species_protector, \
|
||||
@ -210,6 +208,8 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
|
||||
V(resolve_string, resolve_string, ResolveString) \
|
||||
V(return_string, return_string, ReturnString) \
|
||||
V(search_symbol, search_symbol, SearchSymbol) \
|
||||
V(SingleCharacterStringTable, single_character_string_table, \
|
||||
SingleCharacterStringTable) \
|
||||
V(species_symbol, species_symbol, SpeciesSymbol) \
|
||||
V(StaleRegister, stale_register, StaleRegister) \
|
||||
V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) \
|
||||
|
@ -195,8 +195,8 @@ void Assembler::emit(const Immediate& x) {
|
||||
return;
|
||||
}
|
||||
if (!RelocInfo::IsNoInfo(x.rmode_)) RecordRelocInfo(x.rmode_);
|
||||
if (x.is_heap_object_request()) {
|
||||
RequestHeapObject(x.heap_object_request());
|
||||
if (x.is_heap_number_request()) {
|
||||
RequestHeapNumber(x.heap_number_request());
|
||||
emit(0);
|
||||
return;
|
||||
}
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include "src/base/cpu.h"
|
||||
#include "src/codegen/assembler-inl.h"
|
||||
#include "src/codegen/macro-assembler.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/diagnostics/disassembler.h"
|
||||
#include "src/init/v8.h"
|
||||
@ -64,15 +63,8 @@ Immediate Immediate::EmbeddedNumber(double value) {
|
||||
int32_t smi;
|
||||
if (DoubleToSmiInteger(value, &smi)) return Immediate(Smi::FromInt(smi));
|
||||
Immediate result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
|
||||
result.is_heap_object_request_ = true;
|
||||
result.value_.heap_object_request = HeapObjectRequest(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
Immediate Immediate::EmbeddedStringConstant(const StringConstantBase* str) {
|
||||
Immediate result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
|
||||
result.is_heap_object_request_ = true;
|
||||
result.value_.heap_object_request = HeapObjectRequest(str);
|
||||
result.is_heap_number_request_ = true;
|
||||
result.value_.heap_number_request = HeapNumberRequest(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -293,22 +285,12 @@ Register Operand::reg() const {
|
||||
|
||||
bool operator!=(Operand op, XMMRegister r) { return !op.is_reg(r); }
|
||||
|
||||
void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
||||
DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty());
|
||||
for (auto& request : heap_object_requests_) {
|
||||
Handle<HeapObject> object;
|
||||
switch (request.kind()) {
|
||||
case HeapObjectRequest::kHeapNumber:
|
||||
object = isolate->factory()->NewHeapNumber<AllocationType::kOld>(
|
||||
void Assembler::AllocateAndInstallRequestedHeapNumbers(Isolate* isolate) {
|
||||
DCHECK_IMPLIES(isolate == nullptr, heap_number_requests_.empty());
|
||||
for (auto& request : heap_number_requests_) {
|
||||
Handle<HeapObject> object =
|
||||
isolate->factory()->NewHeapNumber<AllocationType::kOld>(
|
||||
request.heap_number());
|
||||
break;
|
||||
case HeapObjectRequest::kStringConstant: {
|
||||
const StringConstantBase* str = request.string();
|
||||
CHECK_NOT_NULL(str);
|
||||
object = str->AllocateStringConstant(isolate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
|
||||
WriteUnalignedValue(pc, object);
|
||||
}
|
||||
@ -353,7 +335,7 @@ void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
|
||||
// that we are still not overlapping instructions and relocation info).
|
||||
DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
|
||||
|
||||
AllocateAndInstallRequestedHeapObjects(isolate);
|
||||
AllocateAndInstallRequestedHeapNumbers(isolate);
|
||||
|
||||
// Set up code descriptor.
|
||||
// TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
|
||||
|
@ -112,29 +112,28 @@ class Immediate {
|
||||
: Immediate(static_cast<intptr_t>(value.ptr())) {}
|
||||
|
||||
static Immediate EmbeddedNumber(double number); // Smi or HeapNumber.
|
||||
static Immediate EmbeddedStringConstant(const StringConstantBase* str);
|
||||
|
||||
static Immediate CodeRelativeOffset(Label* label) { return Immediate(label); }
|
||||
|
||||
bool is_heap_object_request() const {
|
||||
DCHECK_IMPLIES(is_heap_object_request_,
|
||||
bool is_heap_number_request() const {
|
||||
DCHECK_IMPLIES(is_heap_number_request_,
|
||||
rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
|
||||
rmode_ == RelocInfo::CODE_TARGET);
|
||||
return is_heap_object_request_;
|
||||
return is_heap_number_request_;
|
||||
}
|
||||
|
||||
HeapObjectRequest heap_object_request() const {
|
||||
DCHECK(is_heap_object_request());
|
||||
return value_.heap_object_request;
|
||||
HeapNumberRequest heap_number_request() const {
|
||||
DCHECK(is_heap_number_request());
|
||||
return value_.heap_number_request;
|
||||
}
|
||||
|
||||
int immediate() const {
|
||||
DCHECK(!is_heap_object_request());
|
||||
DCHECK(!is_heap_number_request());
|
||||
return value_.immediate;
|
||||
}
|
||||
|
||||
bool is_embedded_object() const {
|
||||
return !is_heap_object_request() &&
|
||||
return !is_heap_number_request() &&
|
||||
rmode() == RelocInfo::FULL_EMBEDDED_OBJECT;
|
||||
}
|
||||
|
||||
@ -178,10 +177,10 @@ class Immediate {
|
||||
|
||||
union Value {
|
||||
Value() {}
|
||||
HeapObjectRequest heap_object_request;
|
||||
HeapNumberRequest heap_number_request;
|
||||
int immediate;
|
||||
} value_;
|
||||
bool is_heap_object_request_ = false;
|
||||
bool is_heap_number_request_ = false;
|
||||
RelocInfo::Mode rmode_;
|
||||
|
||||
friend class Operand;
|
||||
@ -1766,7 +1765,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
|
||||
bool is_optimizable_farjmp(int idx);
|
||||
|
||||
void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
|
||||
void AllocateAndInstallRequestedHeapNumbers(Isolate* isolate);
|
||||
|
||||
int WriteCodeComments();
|
||||
|
||||
|
@ -1661,7 +1661,7 @@ void TurboAssembler::Move(Register dst, Register src) {
|
||||
}
|
||||
|
||||
void TurboAssembler::Move(Register dst, const Immediate& src) {
|
||||
if (!src.is_heap_object_request() && src.is_zero()) {
|
||||
if (!src.is_heap_number_request() && src.is_zero()) {
|
||||
xor_(dst, dst); // Shorter than mov of 32-bit immediate 0.
|
||||
} else if (src.is_external_reference()) {
|
||||
LoadAddress(dst, src.external_reference());
|
||||
@ -1675,7 +1675,7 @@ void TurboAssembler::Move(Operand dst, const Immediate& src) {
|
||||
// stack.
|
||||
if (root_array_available() && options().isolate_independent_code) {
|
||||
if (src.is_embedded_object() || src.is_external_reference() ||
|
||||
src.is_heap_object_request()) {
|
||||
src.is_heap_number_request()) {
|
||||
Push(src);
|
||||
pop(dst);
|
||||
return;
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "src/base/platform/wrappers.h"
|
||||
#include "src/codegen/assembler-inl.h"
|
||||
#include "src/codegen/macro-assembler.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/flags/flags.h"
|
||||
#include "src/init/v8.h"
|
||||
@ -241,26 +240,14 @@ bool Operand::AddressUsesRegister(Register reg) const {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
||||
DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty());
|
||||
for (auto& request : heap_object_requests_) {
|
||||
void Assembler::AllocateAndInstallRequestedHeapNumbers(Isolate* isolate) {
|
||||
DCHECK_IMPLIES(isolate == nullptr, heap_number_requests_.empty());
|
||||
for (auto& request : heap_number_requests_) {
|
||||
Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
|
||||
switch (request.kind()) {
|
||||
case HeapObjectRequest::kHeapNumber: {
|
||||
Handle<HeapNumber> object =
|
||||
isolate->factory()->NewHeapNumber<AllocationType::kOld>(
|
||||
request.heap_number());
|
||||
WriteUnalignedValue(pc, object);
|
||||
break;
|
||||
}
|
||||
case HeapObjectRequest::kStringConstant: {
|
||||
const StringConstantBase* str = request.string();
|
||||
CHECK_NOT_NULL(str);
|
||||
Handle<String> allocated = str->AllocateStringConstant(isolate);
|
||||
WriteUnalignedValue(pc, allocated);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Handle<HeapNumber> object =
|
||||
isolate->factory()->NewHeapNumber<AllocationType::kOld>(
|
||||
request.heap_number());
|
||||
WriteUnalignedValue(pc, object);
|
||||
}
|
||||
}
|
||||
|
||||
@ -392,7 +379,7 @@ void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
|
||||
// that we are still not overlapping instructions and relocation info.
|
||||
DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
|
||||
|
||||
AllocateAndInstallRequestedHeapObjects(isolate);
|
||||
AllocateAndInstallRequestedHeapNumbers(isolate);
|
||||
|
||||
// Set up code descriptor.
|
||||
// TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
|
||||
@ -1696,15 +1683,7 @@ void Assembler::movq_heap_number(Register dst, double value) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex(dst, kInt64Size);
|
||||
emit(0xB8 | dst.low_bits());
|
||||
RequestHeapObject(HeapObjectRequest(value));
|
||||
emit(Immediate64(kNullAddress, RelocInfo::FULL_EMBEDDED_OBJECT));
|
||||
}
|
||||
|
||||
void Assembler::movq_string(Register dst, const StringConstantBase* str) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex(dst, kInt64Size);
|
||||
emit(0xB8 | dst.low_bits());
|
||||
RequestHeapObject(HeapObjectRequest(str));
|
||||
RequestHeapNumber(HeapNumberRequest(value));
|
||||
emit(Immediate64(kNullAddress, RelocInfo::FULL_EMBEDDED_OBJECT));
|
||||
}
|
||||
|
||||
|
@ -589,8 +589,6 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// move.
|
||||
void movq_heap_number(Register dst, double value);
|
||||
|
||||
void movq_string(Register dst, const StringConstantBase* str);
|
||||
|
||||
// Loads a 64-bit immediate into a register, potentially using the constant
|
||||
// pool.
|
||||
void movq(Register dst, int64_t value) { movq(dst, Immediate64(value)); }
|
||||
@ -2555,7 +2553,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
|
||||
bool is_optimizable_farjmp(int idx);
|
||||
|
||||
void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
|
||||
void AllocateAndInstallRequestedHeapNumbers(Isolate* isolate);
|
||||
|
||||
int WriteCodeComments();
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "src/codegen/interface-descriptors-inl.h"
|
||||
#include "src/codegen/macro-assembler.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/codegen/x64/assembler-x64.h"
|
||||
#include "src/codegen/x64/register-x64.h"
|
||||
#include "src/common/globals.h"
|
||||
@ -1988,12 +1987,6 @@ void TurboAssembler::Move(Operand dst, Handle<HeapObject> object,
|
||||
movq(dst, kScratchRegister);
|
||||
}
|
||||
|
||||
void TurboAssembler::MoveStringConstant(Register result,
|
||||
const StringConstantBase* string,
|
||||
RelocInfo::Mode rmode) {
|
||||
movq_string(result, string);
|
||||
}
|
||||
|
||||
void MacroAssembler::Drop(int stack_elements) {
|
||||
if (stack_elements > 0) {
|
||||
addq(rsp, Immediate(stack_elements * kSystemPointerSize));
|
||||
|
@ -24,8 +24,6 @@ namespace internal {
|
||||
// Convenience for platform-independent signatures.
|
||||
using MemOperand = Operand;
|
||||
|
||||
class StringConstantBase;
|
||||
|
||||
struct SmiIndex {
|
||||
SmiIndex(Register index_register, ScaleFactor scale)
|
||||
: reg(index_register), scale(scale) {}
|
||||
@ -353,10 +351,6 @@ class V8_EXPORT_PRIVATE TurboAssembler
|
||||
// Move src0 to dst0 and src1 to dst1, handling possible overlaps.
|
||||
void MovePair(Register dst0, Register src0, Register dst1, Register src1);
|
||||
|
||||
void MoveStringConstant(
|
||||
Register result, const StringConstantBase* string,
|
||||
RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT);
|
||||
|
||||
// Convert smi to word-size sign-extended value.
|
||||
void SmiUntag(Register reg);
|
||||
// Requires dst != src
|
||||
|
@ -138,9 +138,6 @@ class ArmOperandConverter final : public InstructionOperandConverter {
|
||||
return Operand::EmbeddedNumber(constant.ToFloat64().value());
|
||||
case Constant::kExternalReference:
|
||||
return Operand(constant.ToExternalReference());
|
||||
case Constant::kDelayedStringConstant:
|
||||
return Operand::EmbeddedStringConstant(
|
||||
constant.ToDelayedStringConstant());
|
||||
case Constant::kInt64:
|
||||
case Constant::kCompressedHeapObject:
|
||||
case Constant::kHeapObject:
|
||||
|
@ -231,9 +231,6 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
|
||||
case Constant::kCompressedHeapObject: // Fall through.
|
||||
case Constant::kHeapObject:
|
||||
return Operand(constant.ToHeapObject());
|
||||
case Constant::kDelayedStringConstant:
|
||||
return Operand::EmbeddedStringConstant(
|
||||
constant.ToDelayedStringConstant());
|
||||
case Constant::kRpoNumber:
|
||||
UNREACHABLE(); // TODO(dcarney): RPO immediates on arm64.
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "src/codegen/assembler-inl.h"
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/optimized-compilation-info.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/compiler/backend/code-generator-impl.h"
|
||||
#include "src/compiler/globals.h"
|
||||
#include "src/compiler/linkage.h"
|
||||
@ -1286,10 +1285,6 @@ void CodeGenerator::AddTranslationForOperand(Instruction* instr,
|
||||
DCHECK_EQ(MachineType::AnyTagged(), type);
|
||||
literal = DeoptimizationLiteral(constant.ToHeapObject());
|
||||
break;
|
||||
case Constant::kDelayedStringConstant:
|
||||
DCHECK_EQ(MachineRepresentation::kTagged, type.representation());
|
||||
literal = DeoptimizationLiteral(constant.ToDelayedStringConstant());
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -1330,9 +1325,6 @@ Handle<Object> DeoptimizationLiteral::Reify(Isolate* isolate) const {
|
||||
case DeoptimizationLiteralKind::kNumber: {
|
||||
return isolate->factory()->NewNumber(number_);
|
||||
}
|
||||
case DeoptimizationLiteralKind::kString: {
|
||||
return string_->AllocateStringConstant(isolate);
|
||||
}
|
||||
case DeoptimizationLiteralKind::kInvalid: {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -55,34 +55,26 @@ class InstructionOperandIterator {
|
||||
size_t pos_;
|
||||
};
|
||||
|
||||
enum class DeoptimizationLiteralKind { kObject, kNumber, kString, kInvalid };
|
||||
enum class DeoptimizationLiteralKind { kObject, kNumber, kInvalid };
|
||||
|
||||
// Either a non-null Handle<Object>, a double or a StringConstantBase.
|
||||
// Either a non-null Handle<Object> or a double.
|
||||
class DeoptimizationLiteral {
|
||||
public:
|
||||
DeoptimizationLiteral()
|
||||
: kind_(DeoptimizationLiteralKind::kInvalid),
|
||||
object_(),
|
||||
number_(0),
|
||||
string_(nullptr) {}
|
||||
: kind_(DeoptimizationLiteralKind::kInvalid), object_(), number_(0) {}
|
||||
explicit DeoptimizationLiteral(Handle<Object> object)
|
||||
: kind_(DeoptimizationLiteralKind::kObject), object_(object) {
|
||||
CHECK(!object_.is_null());
|
||||
}
|
||||
explicit DeoptimizationLiteral(double number)
|
||||
: kind_(DeoptimizationLiteralKind::kNumber), number_(number) {}
|
||||
explicit DeoptimizationLiteral(const StringConstantBase* string)
|
||||
: kind_(DeoptimizationLiteralKind::kString), string_(string) {}
|
||||
|
||||
Handle<Object> object() const { return object_; }
|
||||
const StringConstantBase* string() const { return string_; }
|
||||
|
||||
bool operator==(const DeoptimizationLiteral& other) const {
|
||||
return kind_ == other.kind_ && object_.equals(other.object_) &&
|
||||
base::bit_cast<uint64_t>(number_) ==
|
||||
base::bit_cast<uint64_t>(other.number_) &&
|
||||
base::bit_cast<intptr_t>(string_) ==
|
||||
base::bit_cast<intptr_t>(other.string_);
|
||||
base::bit_cast<uint64_t>(other.number_);
|
||||
}
|
||||
|
||||
Handle<Object> Reify(Isolate* isolate) const;
|
||||
@ -101,7 +93,6 @@ class DeoptimizationLiteral {
|
||||
|
||||
Handle<Object> object_;
|
||||
double number_ = 0;
|
||||
const StringConstantBase* string_ = nullptr;
|
||||
};
|
||||
|
||||
// These structs hold pc offsets for generated instructions and is only used
|
||||
|
@ -89,9 +89,6 @@ class IA32OperandConverter : public InstructionOperandConverter {
|
||||
return Immediate(constant.ToHeapObject());
|
||||
case Constant::kCompressedHeapObject:
|
||||
break;
|
||||
case Constant::kDelayedStringConstant:
|
||||
return Immediate::EmbeddedStringConstant(
|
||||
constant.ToDelayedStringConstant());
|
||||
case Constant::kInt64:
|
||||
break;
|
||||
case Constant::kRpoNumber:
|
||||
|
@ -365,8 +365,6 @@ class OperandGenerator {
|
||||
return Constant(HeapConstantOf(node->op()));
|
||||
case IrOpcode::kCompressedHeapConstant:
|
||||
return Constant(HeapConstantOf(node->op()), true);
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
return Constant(StringConstantBaseOf(node->op()));
|
||||
case IrOpcode::kDeadValue: {
|
||||
switch (DeadValueRepresentationOf(node->op())) {
|
||||
case MachineRepresentation::kBit:
|
||||
|
@ -497,7 +497,6 @@ InstructionOperand OperandForDeopt(Isolate* isolate, OperandGenerator* g,
|
||||
case IrOpcode::kInt64Constant:
|
||||
case IrOpcode::kFloat32Constant:
|
||||
case IrOpcode::kFloat64Constant:
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
return g->UseImmediate(input);
|
||||
case IrOpcode::kNumberConstant:
|
||||
if (rep == MachineRepresentation::kWord32) {
|
||||
@ -1431,8 +1430,6 @@ void InstructionSelector::VisitNode(Node* node) {
|
||||
if (!IsSmiDouble(value)) MarkAsTagged(node);
|
||||
return VisitConstant(node);
|
||||
}
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
return MarkAsTagged(node), VisitConstant(node);
|
||||
case IrOpcode::kCall:
|
||||
return VisitCall(node);
|
||||
case IrOpcode::kDeoptimizeIf:
|
||||
|
@ -567,13 +567,6 @@ Handle<CodeT> Constant::ToCode() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
const StringConstantBase* Constant::ToDelayedStringConstant() const {
|
||||
DCHECK_EQ(kDelayedStringConstant, type());
|
||||
const StringConstantBase* value =
|
||||
base::bit_cast<StringConstantBase*>(static_cast<intptr_t>(value_));
|
||||
return value;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Constant& constant) {
|
||||
switch (constant.type()) {
|
||||
case Constant::kInt32:
|
||||
@ -591,9 +584,6 @@ std::ostream& operator<<(std::ostream& os, const Constant& constant) {
|
||||
return os << Brief(*constant.ToHeapObject());
|
||||
case Constant::kRpoNumber:
|
||||
return os << "RPO" << constant.ToRpoNumber().ToInt();
|
||||
case Constant::kDelayedStringConstant:
|
||||
return os << "DelayedStringConstant: "
|
||||
<< constant.ToDelayedStringConstant();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -1110,8 +1110,7 @@ class V8_EXPORT_PRIVATE Constant final {
|
||||
kExternalReference,
|
||||
kCompressedHeapObject,
|
||||
kHeapObject,
|
||||
kRpoNumber,
|
||||
kDelayedStringConstant
|
||||
kRpoNumber
|
||||
};
|
||||
|
||||
explicit Constant(int32_t v);
|
||||
@ -1127,8 +1126,6 @@ class V8_EXPORT_PRIVATE Constant final {
|
||||
: type_(is_compressed ? kCompressedHeapObject : kHeapObject),
|
||||
value_(base::bit_cast<intptr_t>(obj)) {}
|
||||
explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
|
||||
explicit Constant(const StringConstantBase* str)
|
||||
: type_(kDelayedStringConstant), value_(base::bit_cast<intptr_t>(str)) {}
|
||||
explicit Constant(RelocatablePtrConstantInfo info);
|
||||
|
||||
Type type() const { return type_; }
|
||||
@ -1185,7 +1182,6 @@ class V8_EXPORT_PRIVATE Constant final {
|
||||
|
||||
Handle<HeapObject> ToHeapObject() const;
|
||||
Handle<CodeT> ToCode() const;
|
||||
const StringConstantBase* ToDelayedStringConstant() const;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
|
@ -5168,11 +5168,6 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Constant::kDelayedStringConstant: {
|
||||
const StringConstantBase* src_constant = src.ToDelayedStringConstant();
|
||||
__ MoveStringConstant(dst, src_constant);
|
||||
break;
|
||||
}
|
||||
case Constant::kRpoNumber:
|
||||
UNREACHABLE(); // TODO(dcarney): load of labels on x64.
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ TNode<Number> CodeAssembler::NumberConstant(double value) {
|
||||
} else {
|
||||
// We allocate the heap number constant eagerly at this point instead of
|
||||
// deferring allocation to code generation
|
||||
// (see AllocateAndInstallRequestedHeapObjects) since that makes it easier
|
||||
// (see AllocateAndInstallRequestedHeapNumbers) since that makes it easier
|
||||
// to generate constant lookups for embedded builtins.
|
||||
return UncheckedCast<Number>(HeapConstant(
|
||||
isolate()->factory()->NewHeapNumberForCodeAssembler(value)));
|
||||
|
@ -91,13 +91,6 @@ DeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const op) {
|
||||
return OpParameter<DeoptimizeParameters>(op);
|
||||
}
|
||||
|
||||
const Operator* CommonOperatorBuilder::DelayedStringConstant(
|
||||
const StringConstantBase* str) {
|
||||
return zone()->New<Operator1<const StringConstantBase*>>(
|
||||
IrOpcode::kDelayedStringConstant, Operator::kPure,
|
||||
"DelayedStringConstant", 0, 0, 0, 1, 0, 0, str);
|
||||
}
|
||||
|
||||
bool operator==(SelectParameters const& lhs, SelectParameters const& rhs) {
|
||||
return lhs.representation() == rhs.representation() &&
|
||||
lhs.hint() == rhs.hint();
|
||||
@ -1242,11 +1235,6 @@ Handle<HeapObject> HeapConstantOf(const Operator* op) {
|
||||
return OpParameter<Handle<HeapObject>>(op);
|
||||
}
|
||||
|
||||
const StringConstantBase* StringConstantBaseOf(const Operator* op) {
|
||||
DCHECK_EQ(IrOpcode::kDelayedStringConstant, op->opcode());
|
||||
return OpParameter<const StringConstantBase*>(op);
|
||||
}
|
||||
|
||||
const char* StaticAssertSourceOf(const Operator* op) {
|
||||
DCHECK_EQ(IrOpcode::kStaticAssert, op->opcode());
|
||||
return OpParameter<const char*>(op);
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "src/base/compiler-specific.h"
|
||||
#include "src/codegen/machine-type.h"
|
||||
#include "src/codegen/reloc-info.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/compiler/feedback-source.h"
|
||||
#include "src/compiler/frame-states.h"
|
||||
@ -20,8 +19,6 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class StringConstantBase;
|
||||
|
||||
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BranchHint);
|
||||
|
||||
namespace compiler {
|
||||
@ -413,9 +410,6 @@ const FrameStateInfo& FrameStateInfoOf(const Operator* op)
|
||||
V8_EXPORT_PRIVATE Handle<HeapObject> HeapConstantOf(const Operator* op)
|
||||
V8_WARN_UNUSED_RESULT;
|
||||
|
||||
const StringConstantBase* StringConstantBaseOf(const Operator* op)
|
||||
V8_WARN_UNUSED_RESULT;
|
||||
|
||||
const char* StaticAssertSourceOf(const Operator* op);
|
||||
|
||||
class SLVerifierHintParameters final {
|
||||
@ -559,8 +553,6 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final
|
||||
const wasm::FunctionSig* signature);
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
const Operator* DelayedStringConstant(const StringConstantBase* str);
|
||||
|
||||
private:
|
||||
Zone* zone() const { return zone_; }
|
||||
|
||||
|
@ -4,24 +4,30 @@
|
||||
|
||||
#include "src/compiler/js-native-context-specialization.h"
|
||||
|
||||
#include "src/base/logging.h"
|
||||
#include "src/base/optional.h"
|
||||
#include "src/builtins/accessors.h"
|
||||
#include "src/codegen/code-factory.h"
|
||||
#include "src/codegen/string-constants.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/compiler/access-builder.h"
|
||||
#include "src/compiler/access-info.h"
|
||||
#include "src/compiler/allocation-builder-inl.h"
|
||||
#include "src/compiler/allocation-builder.h"
|
||||
#include "src/compiler/compilation-dependencies.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/js-heap-broker.h"
|
||||
#include "src/compiler/js-operator.h"
|
||||
#include "src/compiler/linkage.h"
|
||||
#include "src/compiler/map-inference.h"
|
||||
#include "src/compiler/node-matchers.h"
|
||||
#include "src/compiler/property-access-builder.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
#include "src/compiler/type-cache.h"
|
||||
#include "src/handles/handles.h"
|
||||
#include "src/heap/factory.h"
|
||||
#include "src/objects/feedback-vector.h"
|
||||
#include "src/objects/heap-number.h"
|
||||
#include "src/objects/string.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -118,13 +124,13 @@ Reduction JSNativeContextSpecialization::Reduce(Node* node) {
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// If {node} is a HeapConstant<String>, return the String's length. If {node} is
|
||||
// a number, return the maximum size that a stringified number can have.
|
||||
// Otherwise, we can't easily convert {node} into a String, and we return
|
||||
// nullopt.
|
||||
// static
|
||||
base::Optional<size_t> JSNativeContextSpecialization::GetMaxStringLength(
|
||||
JSHeapBroker* broker, Node* node) {
|
||||
if (node->opcode() == IrOpcode::kDelayedStringConstant) {
|
||||
return StringConstantBaseOf(node->op())->GetMaxStringConstantLength();
|
||||
}
|
||||
|
||||
HeapObjectMatcher matcher(node);
|
||||
if (matcher.HasResolvedValue() && matcher.Ref(broker).IsString()) {
|
||||
StringRef input = matcher.Ref(broker).AsString();
|
||||
@ -144,11 +150,10 @@ base::Optional<size_t> JSNativeContextSpecialization::GetMaxStringLength(
|
||||
Reduction JSNativeContextSpecialization::ReduceJSToString(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSToString, node->opcode());
|
||||
Node* const input = node->InputAt(0);
|
||||
Reduction reduction;
|
||||
|
||||
HeapObjectMatcher matcher(input);
|
||||
if (matcher.HasResolvedValue() && matcher.Ref(broker()).IsString()) {
|
||||
reduction = Changed(input); // JSToString(x:string) => x
|
||||
Reduction reduction = Changed(input); // JSToString(x:string) => x
|
||||
ReplaceWithValue(node, reduction.replacement());
|
||||
return reduction;
|
||||
}
|
||||
@ -159,46 +164,50 @@ Reduction JSNativeContextSpecialization::ReduceJSToString(Node* node) {
|
||||
// regressions and the stronger optimization should be re-implemented.
|
||||
NumberMatcher number_matcher(input);
|
||||
if (number_matcher.HasResolvedValue()) {
|
||||
const StringConstantBase* base = shared_zone()->New<NumberToStringConstant>(
|
||||
number_matcher.ResolvedValue());
|
||||
reduction =
|
||||
Replace(graph()->NewNode(common()->DelayedStringConstant(base)));
|
||||
ReplaceWithValue(node, reduction.replacement());
|
||||
return reduction;
|
||||
Handle<Object> num_obj =
|
||||
broker()
|
||||
->local_isolate_or_isolate()
|
||||
->factory()
|
||||
->NewNumber<AllocationType::kOld>(number_matcher.ResolvedValue());
|
||||
Handle<String> num_str =
|
||||
broker()->local_isolate_or_isolate()->factory()->NumberToString(
|
||||
num_obj);
|
||||
Node* reduced = graph()->NewNode(
|
||||
common()->HeapConstant(broker()->CanonicalPersistentHandle(num_str)));
|
||||
|
||||
ReplaceWithValue(node, reduced);
|
||||
return Replace(reduced);
|
||||
}
|
||||
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
base::Optional<const StringConstantBase*>
|
||||
JSNativeContextSpecialization::CreateDelayedStringConstant(Node* node) {
|
||||
if (node->opcode() == IrOpcode::kDelayedStringConstant) {
|
||||
return StringConstantBaseOf(node->op());
|
||||
// Return a String from {node}, which should be either a HeapConstant<String>
|
||||
// (in which case we return the String), or a number (in which case we convert
|
||||
// it to a String).
|
||||
Handle<String> JSNativeContextSpecialization::CreateStringConstant(Node* node) {
|
||||
DCHECK(IrOpcode::IsConstantOpcode(node->opcode()));
|
||||
NumberMatcher number_matcher(node);
|
||||
if (number_matcher.HasResolvedValue()) {
|
||||
Handle<Object> num_obj =
|
||||
broker()
|
||||
->local_isolate_or_isolate()
|
||||
->factory()
|
||||
->NewNumber<AllocationType::kOld>(number_matcher.ResolvedValue());
|
||||
return broker()->local_isolate_or_isolate()->factory()->NumberToString(
|
||||
num_obj);
|
||||
} else {
|
||||
NumberMatcher number_matcher(node);
|
||||
if (number_matcher.HasResolvedValue()) {
|
||||
return shared_zone()->New<NumberToStringConstant>(
|
||||
number_matcher.ResolvedValue());
|
||||
HeapObjectMatcher matcher(node);
|
||||
if (matcher.HasResolvedValue() && matcher.Ref(broker()).IsString()) {
|
||||
return matcher.Ref(broker()).AsString().object();
|
||||
} else {
|
||||
HeapObjectMatcher matcher(node);
|
||||
if (matcher.HasResolvedValue() && matcher.Ref(broker()).IsString()) {
|
||||
StringRef s = matcher.Ref(broker()).AsString();
|
||||
if (!s.length().has_value()) return base::nullopt;
|
||||
return shared_zone()->New<StringLiteral>(
|
||||
s.object(), static_cast<size_t>(s.length().value()));
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool IsStringConstant(JSHeapBroker* broker, Node* node) {
|
||||
if (node->opcode() == IrOpcode::kDelayedStringConstant) {
|
||||
return true;
|
||||
}
|
||||
|
||||
HeapObjectMatcher matcher(node);
|
||||
return matcher.HasResolvedValue() && matcher.Ref(broker).IsString();
|
||||
}
|
||||
@ -310,6 +319,82 @@ Reduction JSNativeContextSpecialization::ReduceJSAsyncFunctionResolve(
|
||||
return Replace(promise);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Concatenates {left} and {right}. The result is fairly similar to creating a
|
||||
// new ConsString with {left} and {right} and then flattening it, which we don't
|
||||
// do because String::Flatten does not support background threads. Rather than
|
||||
// implementing a full String::Flatten for background threads, we prefered to
|
||||
// implement this Concatenate function, which, unlike String::Flatten, doesn't
|
||||
// need to replace ConsStrings by ThinStrings.
|
||||
Handle<String> Concatenate(Handle<String> left, Handle<String> right,
|
||||
JSHeapBroker* broker) {
|
||||
if (left->length() == 0) return right;
|
||||
if (right->length() == 0) return left;
|
||||
|
||||
// Repeated concatenations have a quadratic cost (eg, "s+=a;s+=b;s+=c;...").
|
||||
// Rather than doing static analysis to determine how many concatenations we
|
||||
// there are and how many uses the result of each concatenation have, we
|
||||
// generate ConsString when the result of the concatenation would have more
|
||||
// than {kConstantStringFlattenMaxSize} characters, and flattened SeqString
|
||||
// otherwise.
|
||||
// TODO(dmercadier): ideally, we would like to get rid of this constant, and
|
||||
// always flatten. This requires some care to avoid the quadratic worst-case.
|
||||
constexpr int32_t kConstantStringFlattenMaxSize = 100;
|
||||
|
||||
int32_t length = left->length() + right->length();
|
||||
if (length > kConstantStringFlattenMaxSize) {
|
||||
return broker->local_isolate_or_isolate()
|
||||
->factory()
|
||||
->NewConsString(left, right, AllocationType::kOld)
|
||||
.ToHandleChecked();
|
||||
}
|
||||
|
||||
// If one of the string is not in readonly space, then we need a
|
||||
// SharedStringAccessGuardIfNeeded before accessing its content.
|
||||
bool require_guard = SharedStringAccessGuardIfNeeded::IsNeeded(
|
||||
*left, broker->local_isolate_or_isolate()) ||
|
||||
SharedStringAccessGuardIfNeeded::IsNeeded(
|
||||
*right, broker->local_isolate_or_isolate());
|
||||
SharedStringAccessGuardIfNeeded access_guard(
|
||||
require_guard ? broker->local_isolate_or_isolate() : nullptr);
|
||||
|
||||
if (left->IsOneByteRepresentation() && right->IsOneByteRepresentation()) {
|
||||
// {left} and {right} are 1-byte ==> the result will be 1-byte.
|
||||
Handle<SeqOneByteString> flat =
|
||||
broker->local_isolate_or_isolate()
|
||||
->factory()
|
||||
->NewRawOneByteString(length, AllocationType::kOld)
|
||||
.ToHandleChecked();
|
||||
DisallowGarbageCollection no_gc;
|
||||
String::WriteToFlat(*left, flat->GetChars(no_gc, access_guard), 0,
|
||||
left->length(), GetPtrComprCageBase(*left),
|
||||
access_guard);
|
||||
String::WriteToFlat(
|
||||
*right, flat->GetChars(no_gc, access_guard) + left->length(), 0,
|
||||
right->length(), GetPtrComprCageBase(*right), access_guard);
|
||||
return flat;
|
||||
} else {
|
||||
// One (or both) of {left} and {right} is 2-byte ==> the result will be
|
||||
// 2-byte.
|
||||
Handle<SeqTwoByteString> flat =
|
||||
broker->local_isolate_or_isolate()
|
||||
->factory()
|
||||
->NewRawTwoByteString(length, AllocationType::kOld)
|
||||
.ToHandleChecked();
|
||||
DisallowGarbageCollection no_gc;
|
||||
String::WriteToFlat(*left, flat->GetChars(no_gc, access_guard), 0,
|
||||
left->length(), GetPtrComprCageBase(*left),
|
||||
access_guard);
|
||||
String::WriteToFlat(
|
||||
*right, flat->GetChars(no_gc, access_guard) + left->length(), 0,
|
||||
right->length(), GetPtrComprCageBase(*right), access_guard);
|
||||
return flat;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceJSAdd(Node* node) {
|
||||
// TODO(turbofan): This has to run together with the inlining and
|
||||
// native context specialization to be able to leverage the string
|
||||
@ -322,24 +407,19 @@ Reduction JSNativeContextSpecialization::ReduceJSAdd(Node* node) {
|
||||
|
||||
base::Optional<size_t> lhs_len = GetMaxStringLength(broker(), lhs);
|
||||
base::Optional<size_t> rhs_len = GetMaxStringLength(broker(), rhs);
|
||||
if (!lhs_len || !rhs_len) {
|
||||
return NoChange();
|
||||
}
|
||||
if (!lhs_len || !rhs_len) return NoChange();
|
||||
|
||||
// Fold into DelayedStringConstant if at least one of the parameters is a
|
||||
// string constant and the addition won't throw due to too long result.
|
||||
// Fold if at least one of the parameters is a string constant and the
|
||||
// addition won't throw due to too long result.
|
||||
if (*lhs_len + *rhs_len <= String::kMaxLength &&
|
||||
(IsStringConstant(broker(), lhs) || IsStringConstant(broker(), rhs))) {
|
||||
base::Optional<const StringConstantBase*> left =
|
||||
CreateDelayedStringConstant(lhs);
|
||||
if (!left.has_value()) return NoChange();
|
||||
base::Optional<const StringConstantBase*> right =
|
||||
CreateDelayedStringConstant(rhs);
|
||||
if (!right.has_value()) return NoChange();
|
||||
const StringConstantBase* cons =
|
||||
shared_zone()->New<StringCons>(left.value(), right.value());
|
||||
Handle<String> left = CreateStringConstant(lhs);
|
||||
Handle<String> right = CreateStringConstant(rhs);
|
||||
|
||||
Handle<String> concatenated = Concatenate(left, right, broker());
|
||||
Node* reduced = graph()->NewNode(common()->HeapConstant(
|
||||
broker()->CanonicalPersistentHandle(concatenated)));
|
||||
|
||||
Node* reduced = graph()->NewNode(common()->DelayedStringConstant(cons));
|
||||
ReplaceWithValue(node, reduced);
|
||||
return Replace(reduced);
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ namespace internal {
|
||||
class Factory;
|
||||
class JSGlobalObject;
|
||||
class JSGlobalProxy;
|
||||
class StringConstantBase;
|
||||
|
||||
namespace compiler {
|
||||
|
||||
@ -125,8 +124,7 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
|
||||
|
||||
Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node);
|
||||
|
||||
base::Optional<const StringConstantBase*> CreateDelayedStringConstant(
|
||||
Node* node);
|
||||
Handle<String> CreateStringConstant(Node* node);
|
||||
|
||||
// A triple of nodes that represents a continuation.
|
||||
class ValueEffectControl final {
|
||||
|
@ -212,7 +212,6 @@ class MachineRepresentationInferrer {
|
||||
MachineRepresentation::kTaggedPointer;
|
||||
break;
|
||||
case IrOpcode::kNumberConstant:
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
case IrOpcode::kChangeBitToTagged:
|
||||
case IrOpcode::kIfException:
|
||||
case IrOpcode::kOsrValue:
|
||||
|
@ -421,7 +421,6 @@
|
||||
V(ConvertReceiver) \
|
||||
V(ConvertTaggedHoleToUndefined) \
|
||||
V(DateNow) \
|
||||
V(DelayedStringConstant) \
|
||||
V(EnsureWritableFastElements) \
|
||||
V(FastApiCall) \
|
||||
V(FindOrderedHashMapEntry) \
|
||||
|
@ -399,7 +399,6 @@ Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
|
||||
// Eagerly fold representation changes for constants.
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kHeapConstant:
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
if (use_info.type_check() == TypeCheckKind::kBigInt) break;
|
||||
return node; // No change necessary.
|
||||
case IrOpcode::kInt32Constant:
|
||||
@ -512,7 +511,6 @@ Node* RepresentationChanger::GetTaggedRepresentationFor(
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kNumberConstant:
|
||||
case IrOpcode::kHeapConstant:
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
return node; // No change necessary.
|
||||
case IrOpcode::kInt32Constant:
|
||||
case IrOpcode::kFloat64Constant:
|
||||
|
@ -2161,7 +2161,6 @@ class RepresentationSelector {
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kHeapConstant:
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
return VisitLeaf<T>(node, MachineRepresentation::kTaggedPointer);
|
||||
case IrOpcode::kPointerConstant: {
|
||||
VisitLeaf<T>(node, MachineType::PointerRepresentation());
|
||||
|
@ -322,9 +322,6 @@ OpIndex GraphBuilder::Process(
|
||||
case IrOpcode::kExternalConstant:
|
||||
return assembler.Constant(ConstantOp::Kind::kExternal,
|
||||
OpParameter<ExternalReference>(op));
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
return assembler.Constant(ConstantOp::Kind::kDelayedString,
|
||||
StringConstantBaseOf(op));
|
||||
|
||||
case IrOpcode::kWord32And:
|
||||
return assembler.BitwiseAnd(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
|
@ -232,9 +232,6 @@ void ConstantOp::PrintOptions(std::ostream& os) const {
|
||||
case Kind::kCompressedHeapObject:
|
||||
os << "compressed heap object: " << handle();
|
||||
break;
|
||||
case Kind::kDelayedString:
|
||||
os << delayed_string();
|
||||
break;
|
||||
}
|
||||
os << "]";
|
||||
}
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
namespace v8::internal {
|
||||
class HeapObject;
|
||||
class StringConstantBase;
|
||||
} // namespace v8::internal
|
||||
namespace v8::internal::compiler {
|
||||
class CallDescriptor;
|
||||
@ -867,8 +866,7 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
kTaggedIndex,
|
||||
kExternal,
|
||||
kHeapObject,
|
||||
kCompressedHeapObject,
|
||||
kDelayedString
|
||||
kCompressedHeapObject
|
||||
};
|
||||
|
||||
Kind kind;
|
||||
@ -878,14 +876,12 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
double float64;
|
||||
ExternalReference external;
|
||||
Handle<HeapObject> handle;
|
||||
const StringConstantBase* string;
|
||||
|
||||
Storage(uint64_t integral = 0) : integral(integral) {}
|
||||
Storage(double constant) : float64(constant) {}
|
||||
Storage(float constant) : float32(constant) {}
|
||||
Storage(ExternalReference constant) : external(constant) {}
|
||||
Storage(Handle<HeapObject> constant) : handle(constant) {}
|
||||
Storage(const StringConstantBase* constant) : string(constant) {}
|
||||
} storage;
|
||||
|
||||
static constexpr OpProperties properties = OpProperties::Pure();
|
||||
@ -905,7 +901,6 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
return MachineType::PointerRepresentation();
|
||||
case Kind::kHeapObject:
|
||||
case Kind::kNumber:
|
||||
case Kind::kDelayedString:
|
||||
return MachineRepresentation::kTagged;
|
||||
case Kind::kCompressedHeapObject:
|
||||
return MachineRepresentation::kCompressed;
|
||||
@ -971,11 +966,6 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
return storage.handle;
|
||||
}
|
||||
|
||||
const StringConstantBase* delayed_string() const {
|
||||
DCHECK(kind == Kind::kDelayedString);
|
||||
return storage.string;
|
||||
}
|
||||
|
||||
bool IsZero() const {
|
||||
switch (kind) {
|
||||
case Kind::kWord32:
|
||||
@ -990,7 +980,6 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
case Kind::kExternal:
|
||||
case Kind::kHeapObject:
|
||||
case Kind::kCompressedHeapObject:
|
||||
case Kind::kDelayedString:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
@ -1009,7 +998,6 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
case Kind::kExternal:
|
||||
case Kind::kHeapObject:
|
||||
case Kind::kCompressedHeapObject:
|
||||
case Kind::kDelayedString:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
@ -1044,8 +1032,6 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
case Kind::kHeapObject:
|
||||
case Kind::kCompressedHeapObject:
|
||||
return base::hash_combine(kind, storage.handle.address());
|
||||
case Kind::kDelayedString:
|
||||
return base::hash_combine(kind, storage.string);
|
||||
}
|
||||
}
|
||||
bool operator==(const ConstantOp& other) const {
|
||||
@ -1075,8 +1061,6 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
case Kind::kHeapObject:
|
||||
case Kind::kCompressedHeapObject:
|
||||
return storage.handle.address() == other.storage.handle.address();
|
||||
case Kind::kDelayedString:
|
||||
return storage.string == other.storage.string;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -771,8 +771,6 @@ Node* ScheduleBuilder::ProcessOperation(const ConstantOp& op) {
|
||||
return AddNode(common.Float64Constant(op.float64()), {});
|
||||
case ConstantOp::Kind::kFloat32:
|
||||
return AddNode(common.Float32Constant(op.float32()), {});
|
||||
case ConstantOp::Kind::kDelayedString:
|
||||
return AddNode(common.DelayedStringConstant(op.delayed_string()), {});
|
||||
}
|
||||
}
|
||||
Node* ScheduleBuilder::ProcessOperation(const LoadOp& op) {
|
||||
|
@ -2361,10 +2361,6 @@ Type Typer::Visitor::TypeNewArgumentsElements(Node* node) {
|
||||
|
||||
Type Typer::Visitor::TypeNewConsString(Node* node) { return Type::String(); }
|
||||
|
||||
Type Typer::Visitor::TypeDelayedStringConstant(Node* node) {
|
||||
return Type::String();
|
||||
}
|
||||
|
||||
Type Typer::Visitor::TypeFindOrderedHashMapEntry(Node* node) {
|
||||
return Type::Range(-1.0, FixedArray::kMaxLength, zone());
|
||||
}
|
||||
|
@ -1276,9 +1276,6 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
|
||||
CheckValueInputIs(node, 2, Type::String());
|
||||
CheckTypeIs(node, Type::String());
|
||||
break;
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
CheckTypeIs(node, Type::String());
|
||||
break;
|
||||
case IrOpcode::kAllocate:
|
||||
CheckValueInputIs(node, 0, Type::PlainNumber());
|
||||
break;
|
||||
|
@ -45,19 +45,35 @@ class V8_NODISCARD SharedStringAccessGuardIfNeeded {
|
||||
// Slow version which gets the isolate from the String.
|
||||
explicit SharedStringAccessGuardIfNeeded(String str) {
|
||||
Isolate* isolate = GetIsolateIfNeeded(str);
|
||||
if (isolate != nullptr)
|
||||
if (isolate != nullptr) {
|
||||
mutex_guard.emplace(isolate->internalized_string_access());
|
||||
}
|
||||
}
|
||||
|
||||
static SharedStringAccessGuardIfNeeded NotNeeded() {
|
||||
return SharedStringAccessGuardIfNeeded();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool IsNeeded(String str) {
|
||||
return GetIsolateIfNeeded(str) != nullptr;
|
||||
static bool IsNeeded(String str, LocalIsolate* local_isolate) {
|
||||
return IsNeeded(local_isolate) && IsNeeded(str, false);
|
||||
}
|
||||
|
||||
static bool IsNeeded(String str, bool check_local_heap = true) {
|
||||
if (check_local_heap) {
|
||||
LocalHeap* local_heap = LocalHeap::Current();
|
||||
if (!local_heap || local_heap->is_main_thread()) {
|
||||
// Don't acquire the lock for the main thread.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ReadOnlyHeap::Contains(str)) {
|
||||
// Don't acquire lock for strings in ReadOnlySpace.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool IsNeeded(LocalIsolate* local_isolate) {
|
||||
// TODO(leszeks): Remove the nullptr check for local_isolate.
|
||||
@ -75,16 +91,7 @@ class V8_NODISCARD SharedStringAccessGuardIfNeeded {
|
||||
|
||||
// Returns the Isolate from the String if we need it for the lock.
|
||||
static Isolate* GetIsolateIfNeeded(String str) {
|
||||
LocalHeap* local_heap = LocalHeap::Current();
|
||||
// Don't acquire the lock for the main thread.
|
||||
if (!local_heap || local_heap->is_main_thread()) return nullptr;
|
||||
|
||||
#ifdef V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE
|
||||
// We don't need to guard when the string is in RO space. When compressing
|
||||
// pointers in a per-Isolate cage, GetIsolateFromHeapObject always returns
|
||||
// an Isolate, even for objects in RO space, so manually check.
|
||||
if (ReadOnlyHeap::Contains(str)) return nullptr;
|
||||
#endif
|
||||
if (!IsNeeded(str)) return nullptr;
|
||||
|
||||
Isolate* isolate;
|
||||
if (!GetIsolateFromHeapObject(str, &isolate)) {
|
||||
|
Loading…
Reference in New Issue
Block a user