Commit 71dfcbac authored by jkummerow's avatar jkummerow Committed by Commit bot

[stubs] Consolidate TryToName implementation

This extends TryToName by HeapNumber-to-intptr support and cached array
index retrieval from non-internalized strings, and uses it in the
KeyedLoadIC_Generic stub.

Bonus: avoid needless movsxlq on x64 in LoadFixed{,Double}ArrayElement
helpers by introducing INTPTR_PARAMETER mode.

Review-Url: https://codereview.chromium.org/2277363002
Cr-Commit-Position: refs/heads/master@{#39217}
parent b28b7e13
...@@ -35,7 +35,7 @@ void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) { ...@@ -35,7 +35,7 @@ void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
Node* map = assembler->LoadMap(object); Node* map = assembler->LoadMap(object);
Node* instance_type = assembler->LoadMapInstanceType(map); Node* instance_type = assembler->LoadMapInstanceType(map);
Variable var_index(assembler, MachineRepresentation::kWord32); Variable var_index(assembler, MachineType::PointerRepresentation());
Label keyisindex(assembler), if_iskeyunique(assembler); Label keyisindex(assembler), if_iskeyunique(assembler);
assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique, assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
......
This diff is collapsed.
...@@ -46,7 +46,7 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -46,7 +46,7 @@ class CodeStubAssembler : public compiler::CodeAssembler {
typedef base::Flags<AllocationFlag> AllocationFlags; typedef base::Flags<AllocationFlag> AllocationFlags;
enum ParameterMode { INTEGER_PARAMETERS, SMI_PARAMETERS }; enum ParameterMode { INTEGER_PARAMETERS, SMI_PARAMETERS, INTPTR_PARAMETERS };
compiler::Node* BooleanMapConstant(); compiler::Node* BooleanMapConstant();
compiler::Node* EmptyStringConstant(); compiler::Node* EmptyStringConstant();
...@@ -399,9 +399,9 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -399,9 +399,9 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed); compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed);
template <typename Dictionary> template <typename Dictionary>
void NumberDictionaryLookup(compiler::Node* dictionary, compiler::Node* key, void NumberDictionaryLookup(compiler::Node* dictionary,
Label* if_found, Variable* var_entry, compiler::Node* intptr_index, Label* if_found,
Label* if_not_found); Variable* var_entry, Label* if_not_found);
// Tries to check if {object} has own {unique_name} property. // Tries to check if {object} has own {unique_name} property.
void TryHasOwnProperty(compiler::Node* object, compiler::Node* map, void TryHasOwnProperty(compiler::Node* object, compiler::Node* map,
...@@ -454,9 +454,9 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -454,9 +454,9 @@ class CodeStubAssembler : public compiler::CodeAssembler {
Label* if_not_found, Label* if_bailout); Label* if_not_found, Label* if_bailout);
void TryLookupElement(compiler::Node* object, compiler::Node* map, void TryLookupElement(compiler::Node* object, compiler::Node* map,
compiler::Node* instance_type, compiler::Node* index, compiler::Node* instance_type,
Label* if_found, Label* if_not_found, compiler::Node* intptr_index, Label* if_found,
Label* if_bailout); Label* if_not_found, Label* if_bailout);
// This is a type of a lookup in holder generator function. In case of a // This is a type of a lookup in holder generator function. In case of a
// property lookup the {key} is guaranteed to be a unique name and in case of // property lookup the {key} is guaranteed to be a unique name and in case of
...@@ -579,7 +579,7 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -579,7 +579,7 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* TryToIntptr(compiler::Node* key, Label* miss); compiler::Node* TryToIntptr(compiler::Node* key, Label* miss);
void EmitFastElementsBoundsCheck(compiler::Node* object, void EmitFastElementsBoundsCheck(compiler::Node* object,
compiler::Node* elements, compiler::Node* elements,
compiler::Node* intptr_key, compiler::Node* intptr_index,
compiler::Node* is_jsarray_condition, compiler::Node* is_jsarray_condition,
Label* miss); Label* miss);
void EmitElementLoad(compiler::Node* object, compiler::Node* elements, void EmitElementLoad(compiler::Node* object, compiler::Node* elements,
......
...@@ -234,6 +234,13 @@ Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) { ...@@ -234,6 +234,13 @@ Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
return value; return value;
} }
Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
if (raw_assembler_->machine()->Is64()) {
return raw_assembler_->RoundInt64ToFloat64(value);
}
return raw_assembler_->ChangeInt32ToFloat64(value);
}
#define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \ #define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \
Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); } Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); }
CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP) CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
......
...@@ -283,6 +283,10 @@ class CodeAssembler { ...@@ -283,6 +283,10 @@ class CodeAssembler {
CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP) CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
#undef DECLARE_CODE_ASSEMBLER_UNARY_OP #undef DECLARE_CODE_ASSEMBLER_UNARY_OP
// Changes an intptr_t to a double, e.g. for storing an element index
// outside Smi range in a HeapNumber. Lossless on 32-bit,
// rounds on 64-bit (which doesn't affect valid element indices).
Node* RoundIntPtrToFloat64(Node* value);
// No-op on 32-bit, otherwise zero extend. // No-op on 32-bit, otherwise zero extend.
Node* ChangeUint32ToWord(Node* value); Node* ChangeUint32ToWord(Node* value);
// No-op on 32-bit, otherwise sign extend. // No-op on 32-bit, otherwise sign extend.
......
...@@ -135,7 +135,7 @@ TEST(TryToName) { ...@@ -135,7 +135,7 @@ TEST(TryToName) {
Label passed(&m), failed(&m); Label passed(&m), failed(&m);
Label if_keyisindex(&m), if_keyisunique(&m), if_bailout(&m); Label if_keyisindex(&m), if_keyisunique(&m), if_bailout(&m);
Variable var_index(&m, MachineRepresentation::kWord32); Variable var_index(&m, MachineType::PointerRepresentation());
m.TryToName(key, &if_keyisindex, &var_index, &if_keyisunique, &if_bailout); m.TryToName(key, &if_keyisindex, &var_index, &if_keyisunique, &if_bailout);
...@@ -143,8 +143,8 @@ TEST(TryToName) { ...@@ -143,8 +143,8 @@ TEST(TryToName) {
m.GotoUnless( m.GotoUnless(
m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kKeyIsIndex))), m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kKeyIsIndex))),
&failed); &failed);
m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_index.value()), m.Branch(m.WordEqual(m.SmiUntag(expected_arg), var_index.value()), &passed,
&passed, &failed); &failed);
m.Bind(&if_keyisunique); m.Bind(&if_keyisunique);
m.GotoUnless( m.GotoUnless(
...@@ -184,9 +184,17 @@ TEST(TryToName) { ...@@ -184,9 +184,17 @@ TEST(TryToName) {
} }
{ {
// TryToName(<negative smi>) => bailout. // TryToName(<negative smi>) => if_keyisindex: smi value.
// A subsequent bounds check needs to take care of this case.
Handle<Object> key(Smi::FromInt(-1), isolate); Handle<Object> key(Smi::FromInt(-1), isolate);
ft.CheckTrue(key, expect_bailout); ft.CheckTrue(key, expect_index, key);
}
{
// TryToName(<heap number with int value>) => if_keyisindex: number.
Handle<Object> key(isolate->factory()->NewHeapNumber(153));
Handle<Object> index(Smi::FromInt(153), isolate);
ft.CheckTrue(key, expect_index, index);
} }
{ {
...@@ -208,6 +216,31 @@ TEST(TryToName) { ...@@ -208,6 +216,31 @@ TEST(TryToName) {
ft.CheckTrue(key, expect_index, index); ft.CheckTrue(key, expect_index, index);
} }
{
// TryToName(<internalized uncacheable number string>) => bailout
Handle<Object> key =
isolate->factory()->InternalizeUtf8String("4294967294");
ft.CheckTrue(key, expect_bailout);
}
{
// TryToName(<non-internalized number string>) => if_keyisindex: number.
Handle<String> key = isolate->factory()->NewStringFromAsciiChecked("153");
uint32_t dummy;
CHECK(key->AsArrayIndex(&dummy));
CHECK(key->HasHashCode());
CHECK(!key->IsInternalizedString());
Handle<Object> index(Smi::FromInt(153), isolate);
ft.CheckTrue(key, expect_index, index);
}
{
// TryToName(<number string without cached index>) => bailout.
Handle<String> key = isolate->factory()->NewStringFromAsciiChecked("153");
CHECK(!key->HasHashCode());
ft.CheckTrue(key, expect_bailout);
}
{ {
// TryToName(<non-internalized string>) => bailout. // TryToName(<non-internalized string>) => bailout.
Handle<Object> key = isolate->factory()->NewStringFromAsciiChecked("test"); Handle<Object> key = isolate->factory()->NewStringFromAsciiChecked("test");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment