[stubs] Cleanup CSA::BitFieldDecode(..) and friends.
This CL also introduces IsSetWord<T>(..) and IsSetWord32<T>(..) operations to ease checking if the bit field is set or not. BUG= Review-Url: https://chromiumcodereview.appspot.com/2436893003 Cr-Commit-Position: refs/heads/master@{#40466}
This commit is contained in:
parent
4490a7601c
commit
54194b2d8d
@ -207,7 +207,7 @@ void Builtins::Generate_NumberParseFloat(CodeStubAssembler* assembler) {
|
||||
{
|
||||
// Just return the {input}s cached array index.
|
||||
Node* input_array_index =
|
||||
assembler->BitFieldDecodeWord<String::ArrayIndexValueBits>(
|
||||
assembler->DecodeWordFromWord32<String::ArrayIndexValueBits>(
|
||||
input_hash);
|
||||
assembler->Return(assembler->SmiTag(input_array_index));
|
||||
}
|
||||
@ -340,7 +340,8 @@ void Builtins::Generate_NumberParseInt(CodeStubAssembler* assembler) {
|
||||
|
||||
// Return the cached array index as result.
|
||||
Node* input_index =
|
||||
assembler->BitFieldDecode<String::ArrayIndexValueBits>(input_hash);
|
||||
assembler->DecodeWordFromWord32<String::ArrayIndexValueBits>(
|
||||
input_hash);
|
||||
Node* result = assembler->SmiTag(input_index);
|
||||
assembler->Return(result);
|
||||
}
|
||||
|
@ -488,17 +488,11 @@ void Builtins::Generate_ObjectCreate(CodeStubAssembler* a) {
|
||||
a->GotoUnless(a->WordEqual(a->LoadElements(properties),
|
||||
a->LoadRoot(Heap::kEmptyFixedArrayRootIndex)),
|
||||
&call_runtime);
|
||||
// Jump to the runtime for slow objects.
|
||||
// Handle dictionary objects or fast objects with properties in runtime.
|
||||
Node* bit_field3 = a->LoadMapBitField3(properties_map);
|
||||
Node* is_fast_map = a->Word32Equal(
|
||||
a->BitFieldDecode<Map::DictionaryMap>(bit_field3), a->Int32Constant(0));
|
||||
a->GotoUnless(is_fast_map, &call_runtime);
|
||||
|
||||
a->Branch(
|
||||
a->WordEqual(
|
||||
a->BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bit_field3),
|
||||
a->IntPtrConstant(0)),
|
||||
&no_properties, &call_runtime);
|
||||
a->GotoIf(a->IsSetWord32<Map::DictionaryMap>(bit_field3), &call_runtime);
|
||||
a->Branch(a->IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3),
|
||||
&call_runtime, &no_properties);
|
||||
}
|
||||
|
||||
// Create a new object with the given prototype.
|
||||
|
@ -52,8 +52,9 @@ void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged,
|
||||
// Fail if the array's JSArrayBuffer is not shared.
|
||||
a->Bind(&is_typed_array);
|
||||
Node* array_buffer = a->LoadObjectField(tagged, JSTypedArray::kBufferOffset);
|
||||
Node* is_buffer_shared = a->BitFieldDecode<JSArrayBuffer::IsShared>(
|
||||
a->LoadObjectField(array_buffer, JSArrayBuffer::kBitFieldSlot));
|
||||
Node* is_buffer_shared =
|
||||
a->IsSetWord32<JSArrayBuffer::IsShared>(a->LoadObjectField(
|
||||
array_buffer, JSArrayBuffer::kBitFieldSlot, MachineType::Uint32()));
|
||||
a->Branch(is_buffer_shared, &is_shared, ¬_shared);
|
||||
a->Bind(¬_shared);
|
||||
a->Goto(&invalid);
|
||||
|
@ -658,8 +658,7 @@ void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context,
|
||||
GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)),
|
||||
if_false);
|
||||
|
||||
Node* bit_field2 = LoadMapBitField2(map);
|
||||
Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2);
|
||||
Node* elements_kind = LoadMapElementsKind(map);
|
||||
|
||||
// Bailout if receiver has slow elements.
|
||||
GotoIf(
|
||||
@ -1025,7 +1024,7 @@ Node* CodeStubAssembler::LoadMapInstanceType(Node* map) {
|
||||
|
||||
Node* CodeStubAssembler::LoadMapElementsKind(Node* map) {
|
||||
Node* bit_field2 = LoadMapBitField2(map);
|
||||
return BitFieldDecode<Map::ElementsKindBits>(bit_field2);
|
||||
return DecodeWord32<Map::ElementsKindBits>(bit_field2);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::LoadMapDescriptors(Node* map) {
|
||||
@ -3309,7 +3308,8 @@ Node* CodeStubAssembler::StringToNumber(Node* context, Node* input) {
|
||||
Word32And(hash, Int32Constant(String::kContainsCachedArrayIndexMask));
|
||||
GotoIf(Word32NotEqual(bit, Int32Constant(0)), &runtime);
|
||||
|
||||
var_result.Bind(SmiTag(BitFieldDecode<String::ArrayIndexValueBits>(hash)));
|
||||
var_result.Bind(
|
||||
SmiTag(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash)));
|
||||
Goto(&end);
|
||||
|
||||
Bind(&runtime);
|
||||
@ -3739,12 +3739,16 @@ Node* CodeStubAssembler::ToInteger(Node* context, Node* input,
|
||||
return var_arg.value();
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
|
||||
uint32_t mask) {
|
||||
Node* CodeStubAssembler::DecodeWord32(Node* word32, uint32_t shift,
|
||||
uint32_t mask) {
|
||||
return Word32Shr(Word32And(word32, Int32Constant(mask)),
|
||||
static_cast<int>(shift));
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::DecodeWord(Node* word, uint32_t shift, uint32_t mask) {
|
||||
return WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift));
|
||||
}
|
||||
|
||||
void CodeStubAssembler::SetCounter(StatsCounter* counter, int value) {
|
||||
if (FLAG_native_code_counters && counter->Enabled()) {
|
||||
Node* counter_address = ExternalConstant(ExternalReference(counter));
|
||||
@ -3814,7 +3818,7 @@ void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
|
||||
Goto(if_keyisunique);
|
||||
|
||||
Bind(&if_hascachedindex);
|
||||
var_index->Bind(BitFieldDecodeWord<Name::ArrayIndexValueBits>(hash));
|
||||
var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash));
|
||||
Goto(if_keyisindex);
|
||||
}
|
||||
|
||||
@ -4027,13 +4031,14 @@ void CodeStubAssembler::TryLookupProperty(
|
||||
CSA_ASSERT(Word32Equal(Word32And(bit_field, mask), Int32Constant(0)));
|
||||
|
||||
Node* bit_field3 = LoadMapBitField3(map);
|
||||
Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3);
|
||||
Label if_isfastmap(this), if_isslowmap(this);
|
||||
Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap);
|
||||
Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap,
|
||||
&if_isfastmap);
|
||||
Bind(&if_isfastmap);
|
||||
{
|
||||
Comment("DescriptorArrayLookup");
|
||||
Node* nof = BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bit_field3);
|
||||
Node* nof =
|
||||
DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3);
|
||||
// Bail out to the runtime for large numbers of own descriptors. The stub
|
||||
// only does linear search, which becomes too expensive in that case.
|
||||
{
|
||||
@ -4121,7 +4126,7 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map,
|
||||
name_to_details_offset);
|
||||
var_details->Bind(details);
|
||||
|
||||
Node* location = BitFieldDecode<PropertyDetails::LocationField>(details);
|
||||
Node* location = DecodeWord32<PropertyDetails::LocationField>(details);
|
||||
|
||||
Label if_in_field(this), if_in_descriptor(this), done(this);
|
||||
Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field,
|
||||
@ -4129,9 +4134,9 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map,
|
||||
Bind(&if_in_field);
|
||||
{
|
||||
Node* field_index =
|
||||
BitFieldDecodeWord<PropertyDetails::FieldIndexField>(details);
|
||||
DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details);
|
||||
Node* representation =
|
||||
BitFieldDecode<PropertyDetails::RepresentationField>(details);
|
||||
DecodeWord32<PropertyDetails::RepresentationField>(details);
|
||||
|
||||
Node* inobject_properties = LoadMapInobjectProperties(map);
|
||||
|
||||
@ -4270,7 +4275,7 @@ Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details,
|
||||
var_value.Bind(value);
|
||||
Label done(this);
|
||||
|
||||
Node* kind = BitFieldDecode<PropertyDetails::KindField>(details);
|
||||
Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
|
||||
GotoIf(Word32Equal(kind, Int32Constant(kData)), &done);
|
||||
|
||||
// Accessor case.
|
||||
@ -5161,7 +5166,7 @@ void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements,
|
||||
var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex);
|
||||
Node* details = SmiToWord32(
|
||||
LoadFixedArrayElement(elements, details_index, 0, INTPTR_PARAMETERS));
|
||||
Node* kind = BitFieldDecode<PropertyDetails::KindField>(details);
|
||||
Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
|
||||
// TODO(jkummerow): Support accessors without missing?
|
||||
GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss);
|
||||
// Finally, load the value.
|
||||
@ -5291,8 +5296,7 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
|
||||
|
||||
Node* holder = var_holder.value();
|
||||
Node* handler_word = SmiUntag(var_smi_handler.value());
|
||||
Node* handler_type =
|
||||
WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBits::kMask));
|
||||
Node* handler_type = DecodeWord<LoadHandlerTypeBits>(handler_word);
|
||||
if (support_elements == kSupportElements) {
|
||||
Label property(this);
|
||||
GotoUnless(
|
||||
@ -5302,10 +5306,8 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
|
||||
Comment("element_load");
|
||||
Node* intptr_index = TryToIntptr(p->name, miss);
|
||||
Node* elements = LoadElements(holder);
|
||||
Node* is_jsarray =
|
||||
WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask));
|
||||
Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0));
|
||||
Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word);
|
||||
Node* is_jsarray_condition = IsSetWord<KeyedLoadIsJsArray>(handler_word);
|
||||
Node* elements_kind = DecodeWord<KeyedLoadElementsKind>(handler_word);
|
||||
Label if_hole(this), unimplemented_elements_kind(this);
|
||||
Label* out_of_bounds = miss;
|
||||
EmitElementLoad(holder, elements, elements_kind, intptr_index,
|
||||
@ -5324,9 +5326,7 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
|
||||
Bind(&if_hole);
|
||||
{
|
||||
Comment("convert hole");
|
||||
Node* convert_hole =
|
||||
WordAnd(handler_word, IntPtrConstant(KeyedLoadConvertHole::kMask));
|
||||
GotoIf(WordEqual(convert_hole, IntPtrConstant(0)), miss);
|
||||
GotoUnless(IsSetWord<KeyedLoadConvertHole>(handler_word), miss);
|
||||
Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex);
|
||||
DCHECK(isolate()->heap()->array_protector()->IsPropertyCell());
|
||||
GotoUnless(
|
||||
@ -5348,40 +5348,41 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
|
||||
Bind(&field);
|
||||
{
|
||||
Comment("field_load");
|
||||
Label inobject_double(this), out_of_object(this),
|
||||
out_of_object_double(this);
|
||||
Node* inobject_bit =
|
||||
WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask));
|
||||
Node* double_bit =
|
||||
WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask));
|
||||
Node* offset =
|
||||
WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift));
|
||||
Node* offset = DecodeWord<FieldOffsetOffset>(handler_word);
|
||||
|
||||
GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object);
|
||||
Label inobject(this), out_of_object(this);
|
||||
Branch(IsSetWord<FieldOffsetIsInobject>(handler_word), &inobject,
|
||||
&out_of_object);
|
||||
|
||||
GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double);
|
||||
Return(LoadObjectField(holder, offset));
|
||||
Bind(&inobject);
|
||||
{
|
||||
Label is_double(this);
|
||||
GotoIf(IsSetWord<FieldOffsetIsDouble>(handler_word), &is_double);
|
||||
Return(LoadObjectField(holder, offset));
|
||||
|
||||
Bind(&inobject_double);
|
||||
if (FLAG_unbox_double_fields) {
|
||||
var_double_value.Bind(
|
||||
LoadObjectField(holder, offset, MachineType::Float64()));
|
||||
} else {
|
||||
Node* mutable_heap_number = LoadObjectField(holder, offset);
|
||||
var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
|
||||
Bind(&is_double);
|
||||
if (FLAG_unbox_double_fields) {
|
||||
var_double_value.Bind(
|
||||
LoadObjectField(holder, offset, MachineType::Float64()));
|
||||
} else {
|
||||
Node* mutable_heap_number = LoadObjectField(holder, offset);
|
||||
var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
|
||||
}
|
||||
Goto(&rebox_double);
|
||||
}
|
||||
Goto(&rebox_double);
|
||||
|
||||
Bind(&out_of_object);
|
||||
Node* properties = LoadProperties(holder);
|
||||
Node* value = LoadObjectField(properties, offset);
|
||||
GotoUnless(WordEqual(double_bit, IntPtrConstant(0)),
|
||||
&out_of_object_double);
|
||||
Return(value);
|
||||
{
|
||||
Label is_double(this);
|
||||
Node* properties = LoadProperties(holder);
|
||||
Node* value = LoadObjectField(properties, offset);
|
||||
GotoIf(IsSetWord<FieldOffsetIsDouble>(handler_word), &is_double);
|
||||
Return(value);
|
||||
|
||||
Bind(&out_of_object_double);
|
||||
var_double_value.Bind(LoadHeapNumberValue(value));
|
||||
Goto(&rebox_double);
|
||||
Bind(&is_double);
|
||||
var_double_value.Bind(LoadHeapNumberValue(value));
|
||||
Goto(&rebox_double);
|
||||
}
|
||||
|
||||
Bind(&rebox_double);
|
||||
Return(AllocateHeapNumberWithValue(var_double_value.value()));
|
||||
@ -5391,11 +5392,10 @@ void CodeStubAssembler::HandleLoadICHandlerCase(
|
||||
{
|
||||
Comment("constant_load");
|
||||
Node* descriptors = LoadMapDescriptors(LoadMap(holder));
|
||||
Node* descriptor = WordSar(
|
||||
handler_word, IntPtrConstant(ValueIndexInDescriptorArray::kShift));
|
||||
Node* descriptor = DecodeWord<ValueIndexInDescriptorArray>(handler_word);
|
||||
#if defined(DEBUG)
|
||||
Assert(UintPtrLessThan(descriptor,
|
||||
LoadAndUntagFixedArrayBaseLength(descriptors)));
|
||||
CSA_ASSERT(UintPtrLessThan(
|
||||
descriptor, LoadAndUntagFixedArrayBaseLength(descriptors)));
|
||||
#endif
|
||||
Return(
|
||||
LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS));
|
||||
@ -5629,7 +5629,8 @@ void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
|
||||
const int32_t kMaxLinear = 210;
|
||||
Label stub_cache(this);
|
||||
Node* bitfield3 = LoadMapBitField3(receiver_map);
|
||||
Node* nof = BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bitfield3);
|
||||
Node* nof =
|
||||
DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
|
||||
GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), &stub_cache);
|
||||
Node* descriptors = LoadMapDescriptors(receiver_map);
|
||||
Variable var_name_index(this, MachineType::PointerRepresentation());
|
||||
@ -6436,7 +6437,7 @@ Node* CodeStubAssembler::PageFromAddress(Node* address) {
|
||||
|
||||
Node* CodeStubAssembler::EnumLength(Node* map) {
|
||||
Node* bitfield_3 = LoadMapBitField3(map);
|
||||
Node* enum_length = BitFieldDecode<Map::EnumLengthBits>(bitfield_3);
|
||||
Node* enum_length = DecodeWordFromWord32<Map::EnumLengthBits>(bitfield_3);
|
||||
return SmiTag(enum_length);
|
||||
}
|
||||
|
||||
|
@ -659,20 +659,45 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
// Returns a node that contains a decoded (unsigned!) value of a bit
|
||||
// field |T| in |word32|. Returns result as an uint32 node.
|
||||
template <typename T>
|
||||
compiler::Node* BitFieldDecode(compiler::Node* word32) {
|
||||
return BitFieldDecode(word32, T::kShift, T::kMask);
|
||||
compiler::Node* DecodeWord32(compiler::Node* word32) {
|
||||
return DecodeWord32(word32, T::kShift, T::kMask);
|
||||
}
|
||||
|
||||
// Returns a node that contains a decoded (unsigned!) value of a bit
|
||||
// field |T| in |word|. Returns result as a word-size node.
|
||||
template <typename T>
|
||||
compiler::Node* DecodeWord(compiler::Node* word) {
|
||||
return DecodeWord(word, T::kShift, T::kMask);
|
||||
}
|
||||
|
||||
// Returns a node that contains a decoded (unsigned!) value of a bit
|
||||
// field |T| in |word32|. Returns result as a word-size node.
|
||||
template <typename T>
|
||||
compiler::Node* BitFieldDecodeWord(compiler::Node* word32) {
|
||||
return ChangeUint32ToWord(BitFieldDecode<T>(word32));
|
||||
compiler::Node* DecodeWordFromWord32(compiler::Node* word32) {
|
||||
return DecodeWord<T>(ChangeUint32ToWord(word32));
|
||||
}
|
||||
|
||||
// Decodes an unsigned (!) value from |word32| to an uint32 node.
|
||||
compiler::Node* BitFieldDecode(compiler::Node* word32, uint32_t shift,
|
||||
uint32_t mask);
|
||||
compiler::Node* DecodeWord32(compiler::Node* word32, uint32_t shift,
|
||||
uint32_t mask);
|
||||
|
||||
// Decodes an unsigned (!) value from |word| to a word-size node.
|
||||
compiler::Node* DecodeWord(compiler::Node* word, uint32_t shift,
|
||||
uint32_t mask);
|
||||
|
||||
// Returns true if any of the |T|'s bits in given |word32| are set.
|
||||
template <typename T>
|
||||
compiler::Node* IsSetWord32(compiler::Node* word32) {
|
||||
return Word32NotEqual(Word32And(word32, Int32Constant(T::kMask)),
|
||||
Int32Constant(0));
|
||||
}
|
||||
|
||||
// Returns true if any of the |T|'s bits in given |word| are set.
|
||||
template <typename T>
|
||||
compiler::Node* IsSetWord(compiler::Node* word) {
|
||||
return WordNotEqual(WordAnd(word, IntPtrConstant(T::kMask)),
|
||||
IntPtrConstant(0));
|
||||
}
|
||||
|
||||
void SetCounter(StatsCounter* counter, int value);
|
||||
void IncrementCounter(StatsCounter* counter, int delta);
|
||||
|
@ -2107,7 +2107,7 @@ void Interpreter::DoCreateObjectLiteral(InterpreterAssembler* assembler) {
|
||||
Label if_fast_clone(assembler),
|
||||
if_not_fast_clone(assembler, Label::kDeferred);
|
||||
Node* fast_clone_properties_count =
|
||||
__ BitFieldDecode<CreateObjectLiteralFlags::FastClonePropertiesCountBits>(
|
||||
__ DecodeWord32<CreateObjectLiteralFlags::FastClonePropertiesCountBits>(
|
||||
bytecode_flags);
|
||||
__ Branch(fast_clone_properties_count, &if_fast_clone, &if_not_fast_clone);
|
||||
|
||||
|
@ -61,13 +61,14 @@ TEST(LoadInstanceType) {
|
||||
Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
|
||||
TEST(BitFieldDecode) {
|
||||
TEST(DecodeWordFromWord32) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeStubAssemblerTester m(isolate, descriptor);
|
||||
|
||||
class TestBitField : public BitField<unsigned, 3, 3> {};
|
||||
m.Return(m.SmiTag(m.BitFieldDecode<TestBitField>(m.Int32Constant(0x2f))));
|
||||
m.Return(
|
||||
m.SmiTag(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2f))));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
|
Loading…
Reference in New Issue
Block a user