Commit e2ebe350 authored by Mythri's avatar Mythri Committed by Commit Bot

Update more bytecode handlers to work without feedback vectors

Updates the following bytecode handlers to handle cases when feedback
vector is not allocated:
StaDataPropertyLiteral
CreateRegExpLiteral
CreateArrayLiteral
EmptyArrayLiteral
CreateObjectLiteral
GetTemplateObject
ForInPrepare
ForInNext


Bug: v8:8394
Change-Id: I854cca8dd69539f7e8a17dd8eddb0f9f6d42f762
Reviewed-on: https://chromium-review.googlesource.com/c/1362992
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58107}
parent 9362fa94
......@@ -674,7 +674,7 @@ IGNITION_HANDLER(StaDataPropertyInLiteral, InterpreterAssembler) {
Node* flags = SmiFromInt32(BytecodeOperandFlag(2));
Node* vector_index = SmiTag(BytecodeOperandIdx(3));
Node* feedback_vector = LoadFeedbackVector();
Node* feedback_vector = LoadFeedbackVectorUnchecked();
Node* context = GetContext();
CallRuntime(Runtime::kDefineDataPropertyInLiteral, context, object, name,
......@@ -2369,14 +2369,29 @@ IGNITION_HANDLER(SwitchOnSmiNoFeedback, InterpreterAssembler) {
// <flags> and the pattern in <pattern_idx>.
IGNITION_HANDLER(CreateRegExpLiteral, InterpreterAssembler) {
Node* pattern = LoadConstantPoolEntryAtOperandIndex(0);
Node* feedback_vector = LoadFeedbackVector();
Node* feedback_vector = LoadFeedbackVectorUnchecked();
Node* slot_id = BytecodeOperandIdx(1);
Node* flags = SmiFromInt32(BytecodeOperandFlag(2));
Node* context = GetContext();
VARIABLE(result, MachineRepresentation::kTagged);
Label no_feedback(this, Label::kDeferred), end(this);
GotoIf(IsUndefined(feedback_vector), &no_feedback);
ConstructorBuiltinsAssembler constructor_assembler(state());
Node* result = constructor_assembler.EmitCreateRegExpLiteral(
feedback_vector, slot_id, pattern, flags, context);
SetAccumulator(result);
result.Bind(constructor_assembler.EmitCreateRegExpLiteral(
feedback_vector, slot_id, pattern, flags, context));
Goto(&end);
BIND(&no_feedback);
{
result.Bind(CallRuntime(Runtime::kCreateRegExpLiteral, context,
feedback_vector, SmiTag(slot_id), pattern, flags));
Goto(&end);
}
BIND(&end);
SetAccumulator(result.value());
Dispatch();
}
......@@ -2385,12 +2400,15 @@ IGNITION_HANDLER(CreateRegExpLiteral, InterpreterAssembler) {
// Creates an array literal for literal index <literal_idx> with
// CreateArrayLiteral flags <flags> and constant elements in <element_idx>.
IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
Node* feedback_vector = LoadFeedbackVector();
Node* feedback_vector = LoadFeedbackVectorUnchecked();
Node* slot_id = BytecodeOperandIdx(1);
Node* context = GetContext();
Node* bytecode_flags = BytecodeOperandFlag(2);
Label fast_shallow_clone(this), call_runtime(this, Label::kDeferred);
// No feedback, so handle it as a slow case.
GotoIf(IsUndefined(feedback_vector), &call_runtime);
Branch(IsSetWord32<CreateArrayLiteralFlags::FastCloneSupportedBit>(
bytecode_flags),
&fast_shallow_clone, &call_runtime);
......@@ -2423,13 +2441,31 @@ IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
//
// Creates an empty JSArray literal for literal index <literal_idx>.
IGNITION_HANDLER(CreateEmptyArrayLiteral, InterpreterAssembler) {
Node* feedback_vector = LoadFeedbackVector();
Node* feedback_vector = LoadFeedbackVectorUnchecked();
Node* slot_id = BytecodeOperandIdx(0);
Node* context = GetContext();
Label no_feedback(this, Label::kDeferred), end(this);
VARIABLE(result, MachineRepresentation::kTagged);
GotoIf(IsUndefined(feedback_vector), &no_feedback);
ConstructorBuiltinsAssembler constructor_assembler(state());
Node* result = constructor_assembler.EmitCreateEmptyArrayLiteral(
feedback_vector, slot_id, context);
SetAccumulator(result);
result.Bind(constructor_assembler.EmitCreateEmptyArrayLiteral(
feedback_vector, slot_id, context));
Goto(&end);
BIND(&no_feedback);
{
TNode<Map> array_map = LoadJSArrayElementsMap(GetInitialFastElementsKind(),
LoadNativeContext(context));
result.Bind(AllocateJSArray(GetInitialFastElementsKind(), array_map,
SmiConstant(0), SmiConstant(0), nullptr,
ParameterMode::SMI_PARAMETERS));
Goto(&end);
}
BIND(&end);
SetAccumulator(result.value());
Dispatch();
}
......@@ -2450,12 +2486,15 @@ IGNITION_HANDLER(CreateArrayFromIterable, InterpreterAssembler) {
// Creates an object literal for literal index <literal_idx> with
// CreateObjectLiteralFlags <flags> and constant elements in <element_idx>.
IGNITION_HANDLER(CreateObjectLiteral, InterpreterAssembler) {
Node* feedback_vector = LoadFeedbackVector();
Node* feedback_vector = LoadFeedbackVectorUnchecked();
Node* slot_id = BytecodeOperandIdx(1);
Node* bytecode_flags = BytecodeOperandFlag(2);
// Check if we can do a fast clone or have to call the runtime.
Label if_fast_clone(this), if_not_fast_clone(this, Label::kDeferred);
// No feedback, so handle it as a slow case.
GotoIf(IsUndefined(feedback_vector), &if_not_fast_clone);
// Check if we can do a fast clone or have to call the runtime.
Branch(IsSetWord32<CreateObjectLiteralFlags::FastCloneSupportedBit>(
bytecode_flags),
&if_fast_clone, &if_not_fast_clone);
......@@ -2513,10 +2552,10 @@ IGNITION_HANDLER(CloneObject, InterpreterAssembler) {
Node* smi_flags = SmiTag(raw_flags);
Node* raw_slot = BytecodeOperandIdx(2);
Node* smi_slot = SmiTag(raw_slot);
Node* feedback_vector = LoadFeedbackVector();
Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
Node* context = GetContext();
Node* result = CallBuiltin(Builtins::kCloneObjectIC, context, source,
smi_flags, smi_slot, feedback_vector);
smi_flags, smi_slot, maybe_feedback_vector);
SetAccumulator(result);
Dispatch();
}
......@@ -2527,12 +2566,15 @@ IGNITION_HANDLER(CloneObject, InterpreterAssembler) {
// accumulator, creating and caching the site object on-demand as per the
// specification.
IGNITION_HANDLER(GetTemplateObject, InterpreterAssembler) {
Node* feedback_vector = LoadFeedbackVector();
Node* feedback_vector = LoadFeedbackVectorUnchecked();
Node* slot = BytecodeOperandIdx(1);
Label call_runtime(this, Label::kDeferred);
GotoIf(IsUndefined(feedback_vector), &call_runtime);
TNode<Object> cached_value =
CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
Label call_runtime(this, Label::kDeferred);
GotoIf(WordEqual(cached_value, SmiConstant(0)), &call_runtime);
SetAccumulator(cached_value);
......@@ -2544,7 +2586,13 @@ IGNITION_HANDLER(GetTemplateObject, InterpreterAssembler) {
Node* context = GetContext();
Node* result =
CallRuntime(Runtime::kCreateTemplateObject, context, description);
Label end(this);
GotoIf(IsUndefined(feedback_vector), &end);
StoreFeedbackVectorSlot(feedback_vector, slot, result);
Goto(&end);
Bind(&end);
SetAccumulator(result);
Dispatch();
}
......@@ -2946,7 +2994,7 @@ IGNITION_HANDLER(ForInEnumerate, InterpreterAssembler) {
IGNITION_HANDLER(ForInPrepare, InterpreterAssembler) {
Node* enumerator = GetAccumulator();
Node* vector_index = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
// The {enumerator} is either a Map or a FixedArray.
CSA_ASSERT(this, TaggedIsNotSmi(enumerator));
......@@ -2972,7 +3020,7 @@ IGNITION_HANDLER(ForInPrepare, InterpreterAssembler) {
Node* feedback = SelectSmiConstant(
IntPtrLessThanOrEqual(enum_length, enum_indices_length),
ForInFeedback::kEnumCacheKeysAndIndices, ForInFeedback::kEnumCacheKeys);
UpdateFeedback(feedback, feedback_vector, vector_index);
UpdateFeedback(feedback, maybe_feedback_vector, vector_index);
// Construct the cache info triple.
Node* cache_type = enumerator;
......@@ -2988,7 +3036,7 @@ IGNITION_HANDLER(ForInPrepare, InterpreterAssembler) {
CSA_ASSERT(this, IsFixedArray(enumerator));
// Record the fact that we hit the for-in slow-path.
UpdateFeedback(SmiConstant(ForInFeedback::kAny), feedback_vector,
UpdateFeedback(SmiConstant(ForInFeedback::kAny), maybe_feedback_vector,
vector_index);
// Construct the cache info triple.
......@@ -3010,7 +3058,7 @@ IGNITION_HANDLER(ForInNext, InterpreterAssembler) {
Node* cache_array;
std::tie(cache_type, cache_array) = LoadRegisterPairAtOperandIndex(2);
Node* vector_index = BytecodeOperandIdx(3);
Node* feedback_vector = LoadFeedbackVector();
Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
// Load the next key from the enumeration array.
Node* key = LoadFixedArrayElement(CAST(cache_array), index, 0,
......@@ -3029,7 +3077,7 @@ IGNITION_HANDLER(ForInNext, InterpreterAssembler) {
BIND(&if_slow);
{
// Record the fact that we hit the for-in slow-path.
UpdateFeedback(SmiConstant(ForInFeedback::kAny), feedback_vector,
UpdateFeedback(SmiConstant(ForInFeedback::kAny), maybe_feedback_vector,
vector_index);
// Need to filter the {key} for the {receiver}.
......
......@@ -494,9 +494,15 @@ MaybeHandle<JSObject> CreateLiteralWithoutAllocationSite(
template <typename LiteralHelper>
MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
Handle<FeedbackVector> vector,
MaybeHandle<FeedbackVector> maybe_vector,
int literals_index,
Handle<HeapObject> description, int flags) {
if (maybe_vector.is_null()) {
return CreateLiteralWithoutAllocationSite<LiteralHelper>(
isolate, description, flags);
}
Handle<FeedbackVector> vector = maybe_vector.ToHandleChecked();
FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
CHECK(literals_slot.ToInt() < vector->length());
Handle<Object> literal_site(vector->Get(literals_slot)->cast<Object>(),
......@@ -548,10 +554,15 @@ MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
CONVERT_SMI_ARG_CHECKED(literals_index, 1);
CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
Handle<FeedbackVector> vector = Handle<FeedbackVector>();
if (!maybe_vector->IsUndefined()) {
DCHECK(maybe_vector->IsFeedbackVector());
vector = Handle<FeedbackVector>::cast(maybe_vector);
}
RETURN_RESULT_OR_FAILURE(
isolate, CreateLiteral<ObjectLiteralHelper>(
isolate, vector, literals_index, description, flags));
......@@ -580,10 +591,15 @@ RUNTIME_FUNCTION(Runtime_CreateArrayLiteralWithoutAllocationSite) {
RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
CONVERT_SMI_ARG_CHECKED(literals_index, 1);
CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, elements, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
Handle<FeedbackVector> vector = Handle<FeedbackVector>();
if (!maybe_vector->IsUndefined()) {
DCHECK(maybe_vector->IsFeedbackVector());
vector = Handle<FeedbackVector>::cast(maybe_vector);
}
RETURN_RESULT_OR_FAILURE(
isolate, CreateLiteral<ArrayLiteralHelper>(
isolate, vector, literals_index, elements, flags));
......@@ -592,17 +608,27 @@ RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
CONVERT_SMI_ARG_CHECKED(index, 1);
CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
FeedbackSlot literal_slot(FeedbackVector::ToSlot(index));
Handle<FeedbackVector> vector = Handle<FeedbackVector>();
if (!maybe_vector->IsUndefined()) {
DCHECK(maybe_vector->IsFeedbackVector());
vector = Handle<FeedbackVector>::cast(maybe_vector);
}
Handle<Object> boilerplate;
if (vector.is_null()) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, boilerplate,
JSRegExp::New(isolate, pattern, JSRegExp::Flags(flags)));
return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
}
// Check if boilerplate exists. If not, create it first.
Handle<Object> literal_site(vector->Get(literal_slot)->cast<Object>(),
isolate);
Handle<Object> boilerplate;
if (!HasBoilerplate(literal_site)) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, boilerplate,
......
......@@ -836,21 +836,25 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
CONVERT_SMI_ARG_CHECKED(flag, 3);
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 4);
CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 4);
CONVERT_SMI_ARG_CHECKED(index, 5);
FeedbackNexus nexus(vector, FeedbackVector::ToSlot(index));
if (nexus.ic_state() == UNINITIALIZED) {
if (name->IsUniqueName()) {
nexus.ConfigureMonomorphic(name, handle(object->map(), isolate),
MaybeObjectHandle());
} else {
nexus.ConfigureMegamorphic(PROPERTY);
}
} else if (nexus.ic_state() == MONOMORPHIC) {
if (nexus.FindFirstMap() != object->map() ||
nexus.GetFeedbackExtra() != MaybeObject::FromObject(*name)) {
nexus.ConfigureMegamorphic(PROPERTY);
if (!maybe_vector->IsUndefined()) {
DCHECK(maybe_vector->IsFeedbackVector());
Handle<FeedbackVector> vector = Handle<FeedbackVector>::cast(maybe_vector);
FeedbackNexus nexus(vector, FeedbackVector::ToSlot(index));
if (nexus.ic_state() == UNINITIALIZED) {
if (name->IsUniqueName()) {
nexus.ConfigureMonomorphic(name, handle(object->map(), isolate),
MaybeObjectHandle());
} else {
nexus.ConfigureMegamorphic(PROPERTY);
}
} else if (nexus.ic_state() == MONOMORPHIC) {
if (nexus.FindFirstMap() != object->map() ||
nexus.GetFeedbackExtra() != MaybeObject::FromObject(*name)) {
nexus.ConfigureMegamorphic(PROPERTY);
}
}
}
......
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