[runtime] Extend InstanceType to uint16_t range of values.

Bug: v8:5799
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: Iff62cf07d85b48975d7a21da388bbf6addeb56f1
Reviewed-on: https://chromium-review.googlesource.com/781633
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49589}
This commit is contained in:
Igor Sheludko 2017-11-22 19:04:36 +01:00 committed by Commit Bot
parent 9a0908a7f4
commit cb46310a79
20 changed files with 71 additions and 44 deletions

View File

@ -9152,7 +9152,7 @@ class Internals {
V8_INLINE static int GetInstanceType(const internal::Object* obj) {
typedef internal::Object O;
O* map = ReadField<O*>(obj, kHeapObjectMapOffset);
return ReadField<uint8_t>(map, kMapInstanceTypeOffset);
return ReadField<uint16_t>(map, kMapInstanceTypeOffset);
}
V8_INLINE static int GetOddballKind(const internal::Object* obj) {

View File

@ -1580,7 +1580,7 @@ void MacroAssembler::CompareObjectType(Register object,
void MacroAssembler::CompareInstanceType(Register map,
Register type_reg,
InstanceType type) {
ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
ldrh(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
cmp(type_reg, Operand(type));
}

View File

@ -1678,12 +1678,9 @@ void MacroAssembler::AssertGeneratorObject(Register object) {
Register temp = temps.AcquireX();
Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
// Load instance type
Ldrb(temp, FieldMemOperand(temp, Map::kInstanceTypeOffset));
Label do_check;
// Check if JSGeneratorObject
Cmp(temp, JS_GENERATOR_OBJECT_TYPE);
// Load instance type and check if JSGeneratorObject
CompareInstanceType(temp, temp, JS_GENERATOR_OBJECT_TYPE);
B(eq, &do_check);
// Check if JSAsyncGeneratorObject
@ -2712,7 +2709,7 @@ void MacroAssembler::CompareObjectType(Register object,
void MacroAssembler::CompareInstanceType(Register map,
Register type_reg,
InstanceType type) {
Ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
Ldrh(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
Cmp(type_reg, type);
}

View File

@ -2315,8 +2315,7 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
__ JumpIfSmi(a1, &non_constructor);
// Dispatch based on instance type.
__ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset));
__ lbu(t2, FieldMemOperand(t1, Map::kInstanceTypeOffset));
__ GetObjectType(a1, t1, t2);
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction),
RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));

View File

@ -2334,8 +2334,7 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
__ JumpIfSmi(a1, &non_constructor);
// Dispatch based on instance type.
__ Ld(t1, FieldMemOperand(a1, HeapObject::kMapOffset));
__ Lbu(t2, FieldMemOperand(t1, Map::kInstanceTypeOffset));
__ GetObjectType(a1, t1, t2);
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction),
RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));

View File

@ -1330,7 +1330,7 @@ TNode<Uint32T> CodeStubAssembler::LoadMapBitField3(SloppyTNode<Map> map) {
TNode<Int32T> CodeStubAssembler::LoadMapInstanceType(SloppyTNode<Map> map) {
return UncheckedCast<Int32T>(
LoadObjectField(map, Map::kInstanceTypeOffset, MachineType::Uint8()));
LoadObjectField(map, Map::kInstanceTypeOffset, MachineType::Uint16()));
}
TNode<Int32T> CodeStubAssembler::LoadMapElementsKind(SloppyTNode<Map> map) {

View File

@ -550,7 +550,7 @@ FieldAccess AccessBuilder::ForMapDescriptors() {
FieldAccess AccessBuilder::ForMapInstanceType() {
FieldAccess access = {
kTaggedBase, Map::kInstanceTypeOffset, Handle<Name>(),
MaybeHandle<Map>(), TypeCache::Get().kUint8, MachineType::Uint8(),
MaybeHandle<Map>(), TypeCache::Get().kUint16, MachineType::Uint16(),
kNoWriteBarrier};
return access;
}

View File

@ -151,6 +151,7 @@ const int kMinUInt32 = 0;
const int kUInt8Size = sizeof(uint8_t);
const int kCharSize = sizeof(char);
const int kShortSize = sizeof(short); // NOLINT
const int kUInt16Size = sizeof(uint16_t);
const int kIntSize = sizeof(int);
const int kInt32Size = sizeof(int32_t);
const int kInt64Size = sizeof(int64_t);

View File

@ -2398,7 +2398,6 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
map->set_map_after_allocation(reinterpret_cast<Map*>(root(kMetaMapRootIndex)),
SKIP_WRITE_BARRIER);
map->set_instance_type(instance_type);
WRITE_BYTE_FIELD(map, Map::kSoonToBeInstanceTypeTooOffset, 0);
map->set_instance_size(instance_size);
// Initialize to only containing tagged fields.
if (FLAG_unbox_double_fields) {
@ -2440,7 +2439,6 @@ AllocationResult Heap::AllocateMap(InstanceType instance_type,
map->set_prototype(null_value(), SKIP_WRITE_BARRIER);
map->set_constructor_or_backpointer(null_value(), SKIP_WRITE_BARRIER);
map->set_instance_size(instance_size);
WRITE_BYTE_FIELD(map, Map::kSoonToBeInstanceTypeTooOffset, 0);
if (map->IsJSObjectMap()) {
map->SetInObjectPropertiesStartInWords(instance_size / kPointerSize -
inobject_properties);

View File

@ -483,7 +483,7 @@ void MacroAssembler::CmpObjectType(Register heap_object,
void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
cmpw(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
}
void MacroAssembler::AssertSmi(Register object) {

View File

@ -4118,7 +4118,7 @@ void MacroAssembler::GetObjectType(Register object,
Register map,
Register type_reg) {
lw(map, FieldMemOperand(object, HeapObject::kMapOffset));
lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
lhu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
}

View File

@ -4396,7 +4396,7 @@ void MacroAssembler::GetObjectType(Register object,
Register map,
Register type_reg) {
Ld(map, FieldMemOperand(object, HeapObject::kMapOffset));
Lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
Lhu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
}

View File

@ -3132,12 +3132,13 @@ int HeapObject::SizeFromMap(Map* map) const {
}
InstanceType Map::instance_type() const {
return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
return static_cast<InstanceType>(
READ_UINT16_FIELD(this, kInstanceTypeOffset));
}
void Map::set_instance_type(InstanceType value) {
WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
WRITE_UINT16_FIELD(this, kInstanceTypeOffset, value);
}
int Map::UnusedPropertyFields() const {

View File

@ -554,12 +554,11 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(MODULE_INFO_ENTRY, ModuleInfoEntry, module_info_entry) \
V(ASYNC_GENERATOR_REQUEST, AsyncGeneratorRequest, async_generator_request)
// We use the full 8 bits of the instance_type field to encode heap object
// instance types. The high-order bit (bit 7) is set if the object is not a
// string, and cleared if it is a string.
const uint32_t kIsNotStringMask = 0x80;
// We use the full 16 bits of the instance_type field to encode heap object
// instance types. All the high-order bits (bit 7-15) are cleared if the object
// is a string, and contain set bits if it is not a string.
const uint32_t kIsNotStringMask = 0xff80;
const uint32_t kStringTag = 0x0;
const uint32_t kNotStringTag = 0x80;
// Bit 6 indicates that the object is an internalized string (if set) or not.
// Bit 7 has to be clear as well.
@ -619,7 +618,7 @@ static inline bool IsShortcutCandidate(int type) {
return ((type & kShortcutTypeMask) == kShortcutTypeTag);
}
enum InstanceType : uint8_t {
enum InstanceType : uint16_t {
// String types.
INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kSeqStringTag |
kInternalizedTag, // FIRST_PRIMITIVE_TYPE
@ -670,7 +669,10 @@ enum InstanceType : uint8_t {
kOneByteStringTag | kThinStringTag | kNotInternalizedTag,
// Non-string names
SYMBOL_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE, LAST_NAME_TYPE
SYMBOL_TYPE =
1 + (kIsNotInternalizedMask | kShortExternalStringMask |
kOneByteDataHintMask | kStringEncodingMask |
kStringRepresentationMask), // FIRST_NONSTRING_TYPE, LAST_NAME_TYPE
// Other primitives (cannot contain non-map-word pointers to heap objects).
HEAP_NUMBER_TYPE,
@ -839,6 +841,7 @@ enum InstanceType : uint8_t {
LAST_MAP_ITERATOR_TYPE = JS_MAP_VALUE_ITERATOR_TYPE,
};
STATIC_ASSERT((FIRST_NONSTRING_TYPE & kIsNotStringMask) != kStringTag);
STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType);
STATIC_ASSERT(JS_API_OBJECT_TYPE == Internals::kJSApiObjectType);
STATIC_ASSERT(JS_SPECIAL_API_OBJECT_TYPE == Internals::kJSSpecialApiObjectType);

View File

@ -105,10 +105,7 @@ typedef std::vector<Handle<Map>> MapHandles;
// +----+----------+---------------------------------------------+
// | Int | The second int field |
// `---+----------+---------------------------------------------+
// | Byte | [instance_type] |
// +----------+---------------------------------------------+
// | Byte | Free byte, soon will be used as a second |
// | | byte of [instance_type]. |
// | Short | [instance_type] |
// +----------+---------------------------------------------+
// | Byte | [bit_field] |
// | | - has_non_instance_prototype (bit 0) |
@ -730,9 +727,7 @@ class Map : public HeapObject {
V(kInObjectPropertiesStartOrConstructorFunctionIndexOffset, kUInt8Size) \
V(kUsedOrUnusedInstanceSizeInWordsOffset, kUInt8Size) \
V(kVisitorIdOffset, kUInt8Size) \
V(kInstanceTypeOffset, kUInt8Size) \
/* TODO(ishell): Extend kInstanceTypeOffset field to two bytes. */ \
V(kSoonToBeInstanceTypeTooOffset, kUInt8Size) \
V(kInstanceTypeOffset, kUInt16Size) \
V(kBitFieldOffset, kUInt8Size) \
V(kBitField2Offset, kUInt8Size) \
V(kBitField3Offset, kUInt32Size) \

View File

@ -1365,8 +1365,8 @@ void MacroAssembler::CompareObjectType(Register object, Register map,
void MacroAssembler::CompareInstanceType(Register map, Register type_reg,
InstanceType type) {
STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
STATIC_ASSERT(LAST_TYPE < 256);
lbz(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
STATIC_ASSERT(LAST_TYPE <= 0xffff);
lhz(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
cmpi(type_reg, Operand(type));
}

View File

@ -1392,8 +1392,8 @@ void MacroAssembler::CompareObjectType(Register object, Register map,
void MacroAssembler::CompareInstanceType(Register map, Register type_reg,
InstanceType type) {
STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
STATIC_ASSERT(LAST_TYPE < 256);
LoadlB(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
STATIC_ASSERT(LAST_TYPE <= 0xffff);
LoadHalfWordP(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
CmpP(type_reg, Operand(type));
}

View File

@ -1962,8 +1962,7 @@ void MacroAssembler::CmpObjectType(Register heap_object,
void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
Immediate(static_cast<int8_t>(type)));
cmpw(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
}
void TurboAssembler::SlowTruncateToIDelayed(Zone* zone, Register result_reg) {

View File

@ -15,6 +15,42 @@
namespace v8 {
namespace internal {
namespace {
bool IsInStringInstanceTypeList(InstanceType instance_type) {
switch (instance_type) {
#define TEST_INSTANCE_TYPE(type, ...) \
case InstanceType::type: \
STATIC_ASSERT(InstanceType::type < InstanceType::FIRST_NONSTRING_TYPE);
STRING_TYPE_LIST(TEST_INSTANCE_TYPE)
#undef TEST_INSTANCE_TYPE
return true;
default:
EXPECT_LE(InstanceType::FIRST_NONSTRING_TYPE, instance_type);
return false;
}
}
void CheckOneInstanceType(InstanceType instance_type) {
if (IsInStringInstanceTypeList(instance_type)) {
EXPECT_TRUE((instance_type & kIsNotStringMask) == kStringTag)
<< "Failing IsString mask check for " << instance_type;
} else {
EXPECT_FALSE((instance_type & kIsNotStringMask) == kStringTag)
<< "Failing !IsString mask check for " << instance_type;
}
}
} // namespace
TEST(Object, InstanceTypeList) {
#define TEST_INSTANCE_TYPE(type) CheckOneInstanceType(InstanceType::type);
INSTANCE_TYPE_LIST(TEST_INSTANCE_TYPE)
#undef TEST_INSTANCE_TYPE
}
TEST(Object, InstanceTypeListOrder) {
int current = 0;
int last = -1;

View File

@ -60,7 +60,6 @@ consts_misc = [
{ 'name': 'IsNotStringMask', 'value': 'kIsNotStringMask' },
{ 'name': 'StringTag', 'value': 'kStringTag' },
{ 'name': 'NotStringTag', 'value': 'kNotStringTag' },
{ 'name': 'StringEncodingMask', 'value': 'kStringEncodingMask' },
{ 'name': 'TwoByteStringTag', 'value': 'kTwoByteStringTag' },
@ -249,7 +248,7 @@ extras_accessors = [
'JSTypedArray, length, Object, kLengthOffset',
'Map, instance_size_in_words, char, kInstanceSizeInWordsOffset',
'Map, inobject_properties_start_or_constructor_function_index, char, kInObjectPropertiesStartOrConstructorFunctionIndexOffset',
'Map, instance_type, char, kInstanceTypeOffset',
'Map, instance_type, uint16_t, kInstanceTypeOffset',
'Map, bit_field, char, kBitFieldOffset',
'Map, bit_field2, char, kBitField2Offset',
'Map, bit_field3, int, kBitField3Offset',
@ -373,7 +372,7 @@ def load_objects_from_file(objfilename, checktypes):
# do so without the embedded newlines.
#
for line in objfile:
if (line.startswith('enum InstanceType : uint8_t {')):
if (line.startswith('enum InstanceType : uint16_t {')):
in_insttype = True;
continue;