[tagged-ptr] Introduce FLEXIBLE_ARRAY_MEMBER macro
Because of compiler limitations with the flexible array member extension, in particular around subclassing, introduce a new macro which defines the flexible array members. This also requires accessing flexible array members using a macro, rather than with offsetof. Bug: v8:12710 Change-Id: Ibf8ae9b20bb1a83be7374e439bff484914d7bad1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5148173 Reviewed-by: Anton Bikineev <bikineev@chromium.org> Auto-Submit: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#91765}
This commit is contained in:

committed by
V8 LUCI CQ

parent
ad7450ad27
commit
79d85c3df8
src
builtins
codegen
compiler
maglev
arm
arm64
x64
objects
torque
tools
@ -31,15 +31,15 @@ class IntlBuiltinsAssembler : public CodeStubAssembler {
|
||||
TNode<IntPtrT> PointerToSeqStringData(TNode<String> seq_string) {
|
||||
CSA_DCHECK(this,
|
||||
IsSequentialStringInstanceType(LoadInstanceType(seq_string)));
|
||||
static_assert(offsetof(SeqOneByteString, chars_) ==
|
||||
offsetof(SeqTwoByteString, chars_));
|
||||
return IntPtrAdd(
|
||||
BitcastTaggedToWord(seq_string),
|
||||
IntPtrConstant(offsetof(SeqOneByteString, chars_) - kHeapObjectTag));
|
||||
static_assert(OFFSET_OF_DATA_START(SeqOneByteString) ==
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString));
|
||||
return IntPtrAdd(BitcastTaggedToWord(seq_string),
|
||||
IntPtrConstant(OFFSET_OF_DATA_START(SeqOneByteString) -
|
||||
kHeapObjectTag));
|
||||
}
|
||||
|
||||
TNode<Uint8T> GetChar(TNode<SeqOneByteString> seq_string, int index) {
|
||||
size_t effective_offset = offsetof(SeqOneByteString, chars_) +
|
||||
size_t effective_offset = OFFSET_OF_DATA_START(SeqOneByteString) +
|
||||
sizeof(SeqOneByteString::Char) * index -
|
||||
kHeapObjectTag;
|
||||
return Load<Uint8T>(seq_string, IntPtrConstant(effective_offset));
|
||||
@ -50,7 +50,7 @@ class IntlBuiltinsAssembler : public CodeStubAssembler {
|
||||
void JumpIfStartsWithIgnoreCase(TNode<SeqOneByteString> seq_string,
|
||||
const char* pattern, Label* target) {
|
||||
size_t effective_offset =
|
||||
offsetof(SeqOneByteString, chars_) - kHeapObjectTag;
|
||||
OFFSET_OF_DATA_START(SeqOneByteString) - kHeapObjectTag;
|
||||
TNode<Uint16T> raw =
|
||||
Load<Uint16T>(seq_string, IntPtrConstant(effective_offset));
|
||||
DCHECK_EQ(strlen(pattern), 2);
|
||||
|
@ -32,11 +32,11 @@ TNode<RawPtrT> StringBuiltinsAssembler::DirectStringData(
|
||||
|
||||
BIND(&if_sequential);
|
||||
{
|
||||
static_assert(offsetof(SeqOneByteString, chars_) ==
|
||||
offsetof(SeqTwoByteString, chars_));
|
||||
var_data = RawPtrAdd(
|
||||
ReinterpretCast<RawPtrT>(BitcastTaggedToWord(string)),
|
||||
IntPtrConstant(offsetof(SeqOneByteString, chars_) - kHeapObjectTag));
|
||||
static_assert(OFFSET_OF_DATA_START(SeqOneByteString) ==
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString));
|
||||
var_data = RawPtrAdd(ReinterpretCast<RawPtrT>(BitcastTaggedToWord(string)),
|
||||
IntPtrConstant(OFFSET_OF_DATA_START(SeqOneByteString) -
|
||||
kHeapObjectTag));
|
||||
Goto(&if_join);
|
||||
}
|
||||
|
||||
@ -421,7 +421,7 @@ TNode<String> StringBuiltinsAssembler::StringFromSingleUTF16EncodedCodePoint(
|
||||
TNode<String> value = AllocateSeqTwoByteString(2);
|
||||
StoreNoWriteBarrier(
|
||||
MachineRepresentation::kWord32, value,
|
||||
IntPtrConstant(offsetof(SeqTwoByteString, chars_) - kHeapObjectTag),
|
||||
IntPtrConstant(OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag),
|
||||
codepoint);
|
||||
var_result = value;
|
||||
Goto(&return_result);
|
||||
@ -731,7 +731,7 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(
|
||||
|
||||
// Loop over the {lhs} and {rhs} strings to see if they are equal.
|
||||
constexpr int kBeginOffset =
|
||||
offsetof(SeqOneByteString, chars_) - kHeapObjectTag;
|
||||
OFFSET_OF_DATA_START(SeqOneByteString) - kHeapObjectTag;
|
||||
TNode<IntPtrT> begin = IntPtrConstant(kBeginOffset);
|
||||
TNode<IntPtrT> end = IntPtrAdd(begin, length);
|
||||
TVARIABLE(IntPtrT, var_offset, begin);
|
||||
@ -759,7 +759,7 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(
|
||||
GotoIf(Word64NotEqual(lhs_chunk, rhs_chunk), &char_loop);
|
||||
}
|
||||
|
||||
var_offset = IntPtrConstant(offsetof(SeqOneByteString, chars_) -
|
||||
var_offset = IntPtrConstant(OFFSET_OF_DATA_START(SeqOneByteString) -
|
||||
kHeapObjectTag + kChunkSize);
|
||||
|
||||
Goto(&chunk_loop);
|
||||
@ -1005,7 +1005,7 @@ TF_BUILTIN(StringFromCharCode, StringBuiltinsAssembler) {
|
||||
// The {code16} fits into the SeqOneByteString {one_byte_result}.
|
||||
TNode<IntPtrT> offset = ElementOffsetFromIndex(
|
||||
var_max_index.value(), UINT8_ELEMENTS,
|
||||
offsetof(SeqOneByteString, chars_) - kHeapObjectTag);
|
||||
OFFSET_OF_DATA_START(SeqOneByteString) - kHeapObjectTag);
|
||||
StoreNoWriteBarrier(MachineRepresentation::kWord8, one_byte_result,
|
||||
offset, code16);
|
||||
var_max_index = IntPtrAdd(var_max_index.value(), IntPtrConstant(1));
|
||||
@ -1029,7 +1029,7 @@ TF_BUILTIN(StringFromCharCode, StringBuiltinsAssembler) {
|
||||
// Write the character that caused the 8-bit to 16-bit fault.
|
||||
TNode<IntPtrT> max_index_offset = ElementOffsetFromIndex(
|
||||
var_max_index.value(), UINT16_ELEMENTS,
|
||||
offsetof(SeqTwoByteString, chars_) - kHeapObjectTag);
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag);
|
||||
StoreNoWriteBarrier(MachineRepresentation::kWord16, two_byte_result,
|
||||
max_index_offset, code16);
|
||||
var_max_index = IntPtrAdd(var_max_index.value(), IntPtrConstant(1));
|
||||
@ -1046,7 +1046,7 @@ TF_BUILTIN(StringFromCharCode, StringBuiltinsAssembler) {
|
||||
|
||||
TNode<IntPtrT> offset = ElementOffsetFromIndex(
|
||||
var_max_index.value(), UINT16_ELEMENTS,
|
||||
offsetof(SeqTwoByteString, chars_) - kHeapObjectTag);
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag);
|
||||
StoreNoWriteBarrier(MachineRepresentation::kWord16, two_byte_result,
|
||||
offset, code16);
|
||||
var_max_index = IntPtrAdd(var_max_index.value(), IntPtrConstant(1));
|
||||
@ -1801,9 +1801,9 @@ void StringBuiltinsAssembler::CopyStringCharacters(
|
||||
|
||||
ElementsKind from_kind = from_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
|
||||
ElementsKind to_kind = to_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
|
||||
static_assert(offsetof(SeqOneByteString, chars_) ==
|
||||
offsetof(SeqTwoByteString, chars_));
|
||||
int header_size = offsetof(SeqOneByteString, chars_) - kHeapObjectTag;
|
||||
static_assert(OFFSET_OF_DATA_START(SeqOneByteString) ==
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString));
|
||||
int header_size = OFFSET_OF_DATA_START(SeqOneByteString) - kHeapObjectTag;
|
||||
TNode<IntPtrT> from_offset =
|
||||
ElementOffsetFromIndex(from_index, from_kind, header_size);
|
||||
TNode<IntPtrT> to_offset =
|
||||
@ -1888,7 +1888,7 @@ TNode<String> StringBuiltinsAssembler::AllocAndCopyStringCharacters(
|
||||
// in wasm.tq.
|
||||
TNode<IntPtrT> start_offset = ElementOffsetFromIndex(
|
||||
from_index, UINT16_ELEMENTS,
|
||||
offsetof(SeqTwoByteString, chars_) - kHeapObjectTag);
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag);
|
||||
TNode<IntPtrT> end_offset = IntPtrAdd(
|
||||
start_offset, ElementOffsetFromIndex(character_count, UINT16_ELEMENTS));
|
||||
TNode<IntPtrT> eight_char_loop_end = IntPtrSub(
|
||||
|
@ -7906,7 +7906,7 @@ TNode<String> CodeStubAssembler::StringFromSingleCharCode(TNode<Int32T> code) {
|
||||
TNode<String> result = AllocateSeqTwoByteString(1);
|
||||
StoreNoWriteBarrier(
|
||||
MachineRepresentation::kWord16, result,
|
||||
IntPtrConstant(offsetof(SeqTwoByteString, chars_) - kHeapObjectTag),
|
||||
IntPtrConstant(OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag),
|
||||
code);
|
||||
var_result = result;
|
||||
Goto(&if_done);
|
||||
@ -8023,14 +8023,14 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
|
||||
|
||||
BIND(&if_issequential);
|
||||
{
|
||||
static_assert(offsetof(SeqOneByteString, chars_) ==
|
||||
offsetof(SeqTwoByteString, chars_));
|
||||
static_assert(OFFSET_OF_DATA_START(SeqOneByteString) ==
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString));
|
||||
TNode<RawPtrT> result =
|
||||
ReinterpretCast<RawPtrT>(BitcastTaggedToWord(var_string_.value()));
|
||||
if (ptr_kind == PTR_TO_DATA) {
|
||||
result = RawPtrAdd(
|
||||
result,
|
||||
IntPtrConstant(offsetof(SeqOneByteString, chars_) - kHeapObjectTag));
|
||||
result = RawPtrAdd(result,
|
||||
IntPtrConstant(OFFSET_OF_DATA_START(SeqOneByteString) -
|
||||
kHeapObjectTag));
|
||||
}
|
||||
var_result = result;
|
||||
Goto(&out);
|
||||
@ -8044,9 +8044,9 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
|
||||
TNode<String> string = var_string_.value();
|
||||
TNode<RawPtrT> result = LoadExternalStringResourceDataPtr(CAST(string));
|
||||
if (ptr_kind == PTR_TO_STRING) {
|
||||
result = RawPtrSub(
|
||||
result,
|
||||
IntPtrConstant(offsetof(SeqOneByteString, chars_) - kHeapObjectTag));
|
||||
result = RawPtrSub(result,
|
||||
IntPtrConstant(OFFSET_OF_DATA_START(SeqOneByteString) -
|
||||
kHeapObjectTag));
|
||||
}
|
||||
var_result = result;
|
||||
Goto(&out);
|
||||
|
@ -904,7 +904,7 @@ FieldAccess AccessBuilder::ForExternalStringResourceData() {
|
||||
|
||||
// static
|
||||
ElementAccess AccessBuilder::ForSeqOneByteStringCharacter() {
|
||||
ElementAccess access = {kTaggedBase, offsetof(SeqOneByteString, chars_),
|
||||
ElementAccess access = {kTaggedBase, OFFSET_OF_DATA_START(SeqOneByteString),
|
||||
TypeCache::Get()->kUint8, MachineType::Uint8(),
|
||||
kNoWriteBarrier};
|
||||
return access;
|
||||
@ -912,7 +912,7 @@ ElementAccess AccessBuilder::ForSeqOneByteStringCharacter() {
|
||||
|
||||
// static
|
||||
ElementAccess AccessBuilder::ForSeqTwoByteStringCharacter() {
|
||||
ElementAccess access = {kTaggedBase, offsetof(SeqTwoByteString, chars_),
|
||||
ElementAccess access = {kTaggedBase, OFFSET_OF_DATA_START(SeqTwoByteString),
|
||||
TypeCache::Get()->kUint16, MachineType::Uint16(),
|
||||
kNoWriteBarrier};
|
||||
return access;
|
||||
|
@ -263,8 +263,8 @@ void MaglevAssembler::StringFromCharCode(RegisterSnapshot register_snapshot,
|
||||
register_snapshot.live_registers.set(char_code);
|
||||
__ AllocateTwoByteString(register_snapshot, string, 1);
|
||||
__ and_(scratch, char_code, Operand(0xFFFF));
|
||||
__ strh(scratch,
|
||||
FieldMemOperand(string, offsetof(SeqTwoByteString, chars_)));
|
||||
__ strh(scratch, FieldMemOperand(
|
||||
string, OFFSET_OF_DATA_START(SeqTwoByteString)));
|
||||
if (reallocate_result) {
|
||||
__ Move(result, string);
|
||||
}
|
||||
@ -396,7 +396,7 @@ void MaglevAssembler::StringCharCodeOrCodePointAt(
|
||||
// (CharCodeAt/CodePointAt), since it cannot be the first half of a
|
||||
// surrogate pair.
|
||||
add(index, index,
|
||||
Operand(offsetof(SeqOneByteString, chars_) - kHeapObjectTag));
|
||||
Operand(OFFSET_OF_DATA_START(SeqOneByteString) - kHeapObjectTag));
|
||||
ldrb(result, MemOperand(string, index));
|
||||
b(result_fits_one_byte);
|
||||
|
||||
@ -405,7 +405,7 @@ void MaglevAssembler::StringCharCodeOrCodePointAt(
|
||||
Register scratch = instance_type;
|
||||
lsl(scratch, index, Operand(1));
|
||||
add(scratch, scratch,
|
||||
Operand(offsetof(SeqTwoByteString, chars_) - kHeapObjectTag));
|
||||
Operand(OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag));
|
||||
ldrh(result, MemOperand(string, scratch));
|
||||
|
||||
if (mode == BuiltinStringPrototypeCharCodeOrCodePointAt::kCodePointAt) {
|
||||
@ -423,7 +423,7 @@ void MaglevAssembler::StringCharCodeOrCodePointAt(
|
||||
Register second_code_point = scratch;
|
||||
lsl(index, index, Operand(1));
|
||||
add(index, index,
|
||||
Operand(offsetof(SeqTwoByteString, chars_) - kHeapObjectTag));
|
||||
Operand(OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag));
|
||||
ldrh(second_code_point, MemOperand(string, index));
|
||||
|
||||
// {index} is not needed at this point.
|
||||
|
@ -103,7 +103,7 @@ void BuiltinStringFromCharCode::GenerateCode(MaglevAssembler* masm,
|
||||
__ AllocateTwoByteString(register_snapshot(), result_string, 1);
|
||||
__ Move(scratch, char_code & 0xFFFF);
|
||||
__ strh(scratch, FieldMemOperand(result_string,
|
||||
offsetof(SeqTwoByteString, chars_)));
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString)));
|
||||
if (reallocate_result) {
|
||||
__ Move(ToRegister(result()), result_string);
|
||||
}
|
||||
|
@ -294,8 +294,9 @@ void MaglevAssembler::StringFromCharCode(RegisterSnapshot register_snapshot,
|
||||
register_snapshot.live_registers.set(char_code);
|
||||
__ AllocateTwoByteString(register_snapshot, string, 1);
|
||||
__ And(scratch, char_code, Immediate(0xFFFF));
|
||||
__ Strh(scratch.W(),
|
||||
FieldMemOperand(string, offsetof(SeqTwoByteString, chars_)));
|
||||
__ Strh(
|
||||
scratch.W(),
|
||||
FieldMemOperand(string, OFFSET_OF_DATA_START(SeqTwoByteString)));
|
||||
if (reallocate_result) {
|
||||
__ Move(result, string);
|
||||
}
|
||||
@ -427,7 +428,7 @@ void MaglevAssembler::StringCharCodeOrCodePointAt(
|
||||
// The result of one-byte string will be the same for both modes
|
||||
// (CharCodeAt/CodePointAt), since it cannot be the first half of a
|
||||
// surrogate pair.
|
||||
Add(index, index, offsetof(SeqOneByteString, chars_) - kHeapObjectTag);
|
||||
Add(index, index, OFFSET_OF_DATA_START(SeqOneByteString) - kHeapObjectTag);
|
||||
Ldrb(result, MemOperand(string, index));
|
||||
B(result_fits_one_byte);
|
||||
|
||||
@ -435,7 +436,8 @@ void MaglevAssembler::StringCharCodeOrCodePointAt(
|
||||
// {instance_type} is unused from this point, so we can use as scratch.
|
||||
Register scratch = instance_type;
|
||||
Lsl(scratch, index, 1);
|
||||
Add(scratch, scratch, offsetof(SeqTwoByteString, chars_) - kHeapObjectTag);
|
||||
Add(scratch, scratch,
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag);
|
||||
Ldrh(result, MemOperand(string, scratch));
|
||||
|
||||
if (mode == BuiltinStringPrototypeCharCodeOrCodePointAt::kCodePointAt) {
|
||||
@ -450,7 +452,8 @@ void MaglevAssembler::StringCharCodeOrCodePointAt(
|
||||
|
||||
Register second_code_point = scratch;
|
||||
Lsl(index, index, 1);
|
||||
Add(index, index, offsetof(SeqTwoByteString, chars_) - kHeapObjectTag);
|
||||
Add(index, index,
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString) - kHeapObjectTag);
|
||||
Ldrh(second_code_point, MemOperand(string, index));
|
||||
|
||||
// {index} is not needed at this point.
|
||||
|
@ -107,8 +107,9 @@ void BuiltinStringFromCharCode::GenerateCode(MaglevAssembler* masm,
|
||||
DCHECK(!scratch.Aliases(result_string));
|
||||
__ AllocateTwoByteString(register_snapshot(), result_string, 1);
|
||||
__ Move(scratch, char_code & 0xFFFF);
|
||||
__ Strh(scratch.W(), FieldMemOperand(result_string,
|
||||
offsetof(SeqTwoByteString, chars_)));
|
||||
__ Strh(scratch.W(),
|
||||
FieldMemOperand(result_string,
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString)));
|
||||
if (reallocate_result) {
|
||||
__ Move(ToRegister(result()), result_string);
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ void MaglevAssembler::StringFromCharCode(RegisterSnapshot register_snapshot,
|
||||
register_snapshot.live_registers.set(char_code);
|
||||
__ AllocateTwoByteString(register_snapshot, result, 1);
|
||||
__ andl(char_code, Immediate(0xFFFF));
|
||||
__ movw(FieldOperand(result, offsetof(SeqTwoByteString, chars_)),
|
||||
__ movw(FieldOperand(result, OFFSET_OF_DATA_START(SeqTwoByteString)),
|
||||
char_code);
|
||||
__ jmp(*done);
|
||||
},
|
||||
@ -241,11 +241,11 @@ void MaglevAssembler::StringCharCodeOrCodePointAt(
|
||||
// (CharCodeAt/CodePointAt), since it cannot be the first half of a
|
||||
// surrogate pair.
|
||||
movzxbl(result, FieldOperand(string, index, times_1,
|
||||
offsetof(SeqOneByteString, chars_)));
|
||||
OFFSET_OF_DATA_START(SeqOneByteString)));
|
||||
jmp(result_fits_one_byte);
|
||||
bind(&two_byte_string);
|
||||
movzxwl(result, FieldOperand(string, index, times_2,
|
||||
offsetof(SeqTwoByteString, chars_)));
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString)));
|
||||
|
||||
if (mode == BuiltinStringPrototypeCharCodeOrCodePointAt::kCodePointAt) {
|
||||
Register first_code_point = scratch;
|
||||
@ -263,7 +263,7 @@ void MaglevAssembler::StringCharCodeOrCodePointAt(
|
||||
Register second_code_point = scratch;
|
||||
movzxwl(second_code_point,
|
||||
FieldOperand(string, index, times_2,
|
||||
offsetof(SeqTwoByteString, chars_)));
|
||||
OFFSET_OF_DATA_START(SeqTwoByteString)));
|
||||
|
||||
// {index} is not needed at this point.
|
||||
Register scratch2 = index;
|
||||
|
@ -114,8 +114,9 @@ void BuiltinStringFromCharCode::GenerateCode(MaglevAssembler* masm,
|
||||
__ LoadSingleCharacterString(result_string, char_code);
|
||||
} else {
|
||||
__ AllocateTwoByteString(register_snapshot(), result_string, 1);
|
||||
__ movw(FieldOperand(result_string, offsetof(SeqTwoByteString, chars_)),
|
||||
Immediate(char_code & 0xFFFF));
|
||||
__ movw(
|
||||
FieldOperand(result_string, OFFSET_OF_DATA_START(SeqTwoByteString)),
|
||||
Immediate(char_code & 0xFFFF));
|
||||
}
|
||||
} else {
|
||||
MaglevAssembler::ScratchRegisterScope temps(masm);
|
||||
|
@ -1026,7 +1026,7 @@ uint8_t SeqOneByteString::Get(
|
||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||
USE(access_guard);
|
||||
DCHECK(index >= 0 && index < length());
|
||||
return chars_[index];
|
||||
return chars()[index];
|
||||
}
|
||||
|
||||
void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
|
||||
@ -1034,7 +1034,7 @@ void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
|
||||
DCHECK_GE(index, 0);
|
||||
DCHECK_LT(index, length());
|
||||
DCHECK_LE(value, kMaxOneByteCharCode);
|
||||
chars_[index] = value;
|
||||
chars()[index] = value;
|
||||
}
|
||||
|
||||
void SeqOneByteString::SeqOneByteStringSetChars(int index,
|
||||
@ -1043,18 +1043,18 @@ void SeqOneByteString::SeqOneByteStringSetChars(int index,
|
||||
DisallowGarbageCollection no_gc;
|
||||
DCHECK_LE(0, index);
|
||||
DCHECK_LT(index + string_length, length());
|
||||
void* address = static_cast<void*>(&chars_[index]);
|
||||
void* address = static_cast<void*>(&chars()[index]);
|
||||
memcpy(address, string, string_length);
|
||||
}
|
||||
|
||||
Address SeqOneByteString::GetCharsAddress() const {
|
||||
return reinterpret_cast<Address>(chars_);
|
||||
return reinterpret_cast<Address>(&chars()[0]);
|
||||
}
|
||||
|
||||
uint8_t* SeqOneByteString::GetChars(const DisallowGarbageCollection& no_gc) {
|
||||
USE(no_gc);
|
||||
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(this));
|
||||
return chars_;
|
||||
return chars();
|
||||
}
|
||||
|
||||
uint8_t* SeqOneByteString::GetChars(
|
||||
@ -1062,17 +1062,17 @@ uint8_t* SeqOneByteString::GetChars(
|
||||
const SharedStringAccessGuardIfNeeded& access_guard) {
|
||||
USE(no_gc);
|
||||
USE(access_guard);
|
||||
return chars_;
|
||||
return chars();
|
||||
}
|
||||
|
||||
Address SeqTwoByteString::GetCharsAddress() const {
|
||||
return reinterpret_cast<Address>(chars_);
|
||||
return reinterpret_cast<Address>(&chars()[0]);
|
||||
}
|
||||
|
||||
base::uc16* SeqTwoByteString::GetChars(const DisallowGarbageCollection& no_gc) {
|
||||
USE(no_gc);
|
||||
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(this));
|
||||
return chars_;
|
||||
return chars();
|
||||
}
|
||||
|
||||
base::uc16* SeqTwoByteString::GetChars(
|
||||
@ -1080,20 +1080,20 @@ base::uc16* SeqTwoByteString::GetChars(
|
||||
const SharedStringAccessGuardIfNeeded& access_guard) {
|
||||
USE(no_gc);
|
||||
USE(access_guard);
|
||||
return chars_;
|
||||
return chars();
|
||||
}
|
||||
|
||||
uint16_t SeqTwoByteString::Get(
|
||||
int index, const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||
USE(access_guard);
|
||||
DCHECK(index >= 0 && index < length());
|
||||
return chars_[index];
|
||||
return chars()[index];
|
||||
}
|
||||
|
||||
void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
|
||||
DisallowGarbageCollection no_gc;
|
||||
DCHECK(index >= 0 && index < length());
|
||||
chars_[index] = value;
|
||||
chars()[index] = value;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -814,7 +814,7 @@ V8_OBJECT class SeqOneByteString : public SeqString {
|
||||
friend class compiler::AccessBuilder;
|
||||
friend class TorqueGeneratedSeqOneByteStringAsserts;
|
||||
|
||||
Char chars_[];
|
||||
FLEXIBLE_ARRAY_MEMBER(Char, chars);
|
||||
} V8_OBJECT_END;
|
||||
|
||||
template <>
|
||||
@ -887,7 +887,7 @@ V8_OBJECT class SeqTwoByteString : public SeqString {
|
||||
friend class compiler::AccessBuilder;
|
||||
friend class TorqueGeneratedSeqTwoByteStringAsserts;
|
||||
|
||||
Char chars_[];
|
||||
FLEXIBLE_ARRAY_MEMBER(Char, chars);
|
||||
} V8_OBJECT_END;
|
||||
|
||||
template <>
|
||||
|
@ -63,6 +63,46 @@ class UnalignedDoubleMember {
|
||||
static_assert(alignof(UnalignedDoubleMember) == alignof(Tagged_t));
|
||||
static_assert(sizeof(UnalignedDoubleMember) == sizeof(double));
|
||||
|
||||
// FLEXIBLE_ARRAY_MEMBER(T, name) represents a marker for a variable-sized
|
||||
// suffix of members for a type.
|
||||
//
|
||||
// It behaves as if it were the last member of a class, and creates an accessor
|
||||
// for `T* name()`.
|
||||
//
|
||||
// This macro is used instead of the C99 flexible array member syntax, because
|
||||
//
|
||||
// a) That syntax is only in C++ as an extension,
|
||||
// b) On all our major compilers, it doesn't allow the class to have
|
||||
// subclasses (which means it doesn't work for e.g. TaggedArrayBase or
|
||||
// BigIntBase),
|
||||
// c) The similar zero-length array extension _also_ doesn't allow subclasses
|
||||
// on some compilers (specifically, MSVC).
|
||||
#define FLEXIBLE_ARRAY_MEMBER(Type, name) \
|
||||
/* Some typedefs so that error messages are a bit more transparent */ \
|
||||
using Only_one_FLEXIBLE_ARRAY_MEMBER_allowed_per_class = void; \
|
||||
using OFFSET_OF_DATA_START_needs_class_with_FLEXIBLE_ARRAY_MEMBER = void; \
|
||||
\
|
||||
Type* name() { \
|
||||
static_assert(alignof(Type) <= alignof(decltype(*this))); \
|
||||
return reinterpret_cast<Type*>(this + 1); \
|
||||
} \
|
||||
const Type* name() const { \
|
||||
static_assert(alignof(Type) <= alignof(decltype(*this))); \
|
||||
return reinterpret_cast<const Type*>(this + 1); \
|
||||
} \
|
||||
using FlexibleDataType = Type
|
||||
|
||||
// OFFSET_OF_DATA_START(T) returns the offset of the FLEXIBLE_ARRAY_MEMBER of
|
||||
// the class T.
|
||||
//
|
||||
// It forces an access of a dummy typedef in the class to make sure that it is
|
||||
// only used on classes with a FLEXIBLE_ARRAY_MEMBER.
|
||||
#define OFFSET_OF_DATA_START(Type) \
|
||||
(static_cast< \
|
||||
typename Type:: \
|
||||
OFFSET_OF_DATA_START_needs_class_with_FLEXIBLE_ARRAY_MEMBER>(0), \
|
||||
sizeof(Type))
|
||||
|
||||
// This helper static class represents a tagged field of type T at offset
|
||||
// kFieldOffset inside some host HeapObject.
|
||||
// For full-pointer mode this type adds no overhead but when pointer
|
||||
|
@ -4346,8 +4346,12 @@ void CppClassGenerator::GenerateCppObjectLayoutDefinitionAsserts() {
|
||||
for (auto f : type_->fields()) {
|
||||
std::string field_offset =
|
||||
"k" + CamelifyString(f.name_and_type.name) + "Offset";
|
||||
impl_ << " static_assert(" << field_offset
|
||||
<< " == offsetof(" + name_ + ", " << f.name_and_type.name << "_),\n"
|
||||
std::string cpp_field_offset =
|
||||
f.index.has_value()
|
||||
? "OFFSET_OF_DATA_START(" + name_ + ")"
|
||||
: "offsetof(" + name_ + ", " + f.name_and_type.name + "_)";
|
||||
impl_ << " static_assert(" << field_offset << " == " << cpp_field_offset
|
||||
<< ",\n"
|
||||
<< " \"Value of " << name_ << "::" << field_offset
|
||||
<< " defined in Torque and offset of field " << name_
|
||||
<< "::" << f.name_and_type.name << " in C++ do not match\");\n";
|
||||
|
@ -523,8 +523,8 @@ extras_accessors = [
|
||||
'Oddball, kind, int, offsetof(Oddball, kind_)',
|
||||
'HeapNumber, value, double, kValueOffset',
|
||||
'ExternalString, resource, Object, offsetof(ExternalString, resource_)',
|
||||
'SeqOneByteString, chars, char, offsetof(SeqOneByteString, chars_)',
|
||||
'SeqTwoByteString, chars, char, offsetof(SeqTwoByteString, chars_)',
|
||||
'SeqOneByteString, chars, char, OFFSET_OF_DATA_START(SeqOneByteString)',
|
||||
'SeqTwoByteString, chars, char, OFFSET_OF_DATA_START(SeqTwoByteString)',
|
||||
'UncompiledData, inferred_name, String, kInferredNameOffset',
|
||||
'UncompiledData, start_position, int32_t, kStartPositionOffset',
|
||||
'UncompiledData, end_position, int32_t, kEndPositionOffset',
|
||||
@ -844,7 +844,8 @@ def parse_field(call):
|
||||
offset = args[2];
|
||||
dtype = 'SMI'
|
||||
|
||||
if offset.startswith("offsetof("):
|
||||
if offset.startswith("offsetof(") or offset.startswith(
|
||||
"OFFSET_OF_DATA_START("):
|
||||
offsetof_fields.append((klass, field, offset))
|
||||
value = 'OffsetsForDebug::%s_%s' % (klass, field)
|
||||
else:
|
||||
|
Reference in New Issue
Block a user