Commit 585e3d16 authored by Creddy's avatar Creddy Committed by Commit Bot

[runtime] Fix the bug that caused performance regression with prototype lookup

Word32Not was used instead of Word32BinaryNot which caused unecssary runtime lookup.
This CL fixed the performance regression https://crrev.com/c/1145438.

Bug: chromium:868799
Change-Id: I9e070de6155797e52dd9b461a9660cb003509a57
Reviewed-on: https://chromium-review.googlesource.com/1169808
Commit-Queue: Chandan Reddy <chandanreddy@google.com>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55100}
parent c46915b9
......@@ -2454,7 +2454,7 @@ TNode<Map> CodeStubAssembler::LoadJSArrayElementsMap(
LoadContextElement(native_context, Context::ArrayMapIndex(kind)));
}
TNode<Word32T> CodeStubAssembler::IsGeneratorFunction(
TNode<BoolT> CodeStubAssembler::IsGeneratorFunction(
TNode<JSFunction> function) {
TNode<SharedFunctionInfo> const shared_function_info =
CAST(LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset));
......@@ -2464,7 +2464,7 @@ TNode<Word32T> CodeStubAssembler::IsGeneratorFunction(
shared_function_info, SharedFunctionInfo::kFlagsOffset,
MachineType::Uint32()));
return Word32Or(
return TNode<BoolT>::UncheckedCast(Word32Or(
Word32Or(
Word32Or(
Word32Equal(function_kind,
......@@ -2475,25 +2475,26 @@ TNode<Word32T> CodeStubAssembler::IsGeneratorFunction(
Word32Equal(function_kind,
Int32Constant(FunctionKind::kGeneratorFunction))),
Word32Equal(function_kind,
Int32Constant(FunctionKind::kConciseGeneratorMethod)));
Int32Constant(FunctionKind::kConciseGeneratorMethod))));
}
TNode<Word32T> CodeStubAssembler::HasPrototypeProperty(
TNode<JSFunction> function) {
TNode<Int32T> mask = Int32Constant(Map::HasPrototypeSlotBit::kMask |
Map::IsConstructorBit::kMask);
return Word32Or(
Word32Equal(Word32And(LoadMapBitField(LoadMap(function)), mask), mask),
IsGeneratorFunction(function));
TNode<BoolT> CodeStubAssembler::HasPrototypeProperty(TNode<JSFunction> function,
TNode<Map> map) {
// (has_prototype_slot() && IsConstructor()) ||
// IsGeneratorFunction(shared()->kind())
uint32_t mask =
Map::HasPrototypeSlotBit::kMask | Map::IsConstructorBit::kMask;
return TNode<BoolT>::UncheckedCast(
Word32Or(IsAllSetWord32(LoadMapBitField(map), mask),
IsGeneratorFunction(function)));
}
TNode<Word32T> CodeStubAssembler::PrototypeRequiresRuntimeLookup(
TNode<JSFunction> function) {
TNode<Map> map = LoadMap(function);
return Word32Or(
Word32BinaryNot(HasPrototypeProperty(function)),
IsSetWord32<Map::HasNonInstancePrototypeBit>(LoadMapBitField(map)));
void CodeStubAssembler::GotoIfPrototypeRequiresRuntimeLookup(
TNode<JSFunction> function, TNode<Map> map, Label* runtime) {
// !has_prototype_property() || has_non_instance_prototype()
GotoIfNot(HasPrototypeProperty(function, map), runtime);
GotoIf(IsSetWord32<Map::HasNonInstancePrototypeBit>(LoadMapBitField(map)),
runtime);
}
Node* CodeStubAssembler::LoadJSFunctionPrototype(Node* function,
......@@ -8385,7 +8386,8 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
LoadObjectField(accessor_info, AccessorInfo::kNameOffset)),
if_bailout);
GotoIf(PrototypeRequiresRuntimeLookup(CAST(receiver)), if_bailout);
GotoIfPrototypeRequiresRuntimeLookup(CAST(receiver), CAST(receiver_map),
if_bailout);
var_value.Bind(LoadJSFunctionPrototype(receiver, if_bailout));
Goto(&done);
}
......@@ -8839,7 +8841,8 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
GotoIfNot(InstanceTypeEqual(callable_instance_type, JS_FUNCTION_TYPE),
&return_runtime);
GotoIf(PrototypeRequiresRuntimeLookup(CAST(callable)), &return_runtime);
GotoIfPrototypeRequiresRuntimeLookup(CAST(callable), CAST(callable_map),
&return_runtime);
// Get the "prototype" (or initial map) of the {callable}.
Node* callable_prototype =
......
......@@ -1116,9 +1116,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<Map> LoadJSArrayElementsMap(SloppyTNode<Int32T> kind,
SloppyTNode<Context> native_context);
TNode<Word32T> IsGeneratorFunction(TNode<JSFunction> function);
TNode<Word32T> HasPrototypeProperty(TNode<JSFunction> function);
TNode<Word32T> PrototypeRequiresRuntimeLookup(TNode<JSFunction> function);
TNode<BoolT> IsGeneratorFunction(TNode<JSFunction> function);
TNode<BoolT> HasPrototypeProperty(TNode<JSFunction> function, TNode<Map> map);
void GotoIfPrototypeRequiresRuntimeLookup(TNode<JSFunction> function,
TNode<Map> map, Label* runtime);
// Load the "prototype" property of a JSFunction.
Node* LoadJSFunctionPrototype(Node* function, Label* if_bailout);
......@@ -2053,6 +2054,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Int32Constant(0));
}
// Returns true if all of the mask's bits in a given |word32| are set.
TNode<BoolT> IsAllSetWord32(SloppyTNode<Word32T> word32, uint32_t mask) {
TNode<Int32T> const_mask = Int32Constant(mask);
return Word32Equal(Word32And(word32, const_mask), const_mask);
}
// Returns true if any of the |T|'s bits in given |word| are set.
template <typename T>
TNode<BoolT> IsSetWord(SloppyTNode<WordT> word) {
......
......@@ -2494,8 +2494,8 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
&not_function_prototype);
GotoIfNot(IsPrototypeString(p->name), &not_function_prototype);
GotoIf(PrototypeRequiresRuntimeLookup(CAST(receiver)),
&not_function_prototype);
GotoIfPrototypeRequiresRuntimeLookup(CAST(receiver), CAST(receiver_map),
&not_function_prototype);
Return(LoadJSFunctionPrototype(receiver, &miss));
BIND(&not_function_prototype);
}
......
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