[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:
ishell 2016-10-20 05:27:18 -07:00 committed by Commit bot
parent 4490a7601c
commit 54194b2d8d
7 changed files with 103 additions and 80 deletions

View File

@ -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);
}

View File

@ -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.

View File

@ -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, &not_shared);
a->Bind(&not_shared);
a->Goto(&invalid);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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();