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

Don't use feedback vector to infer IC kind and language mode

Currently, the runtime IC functions deduce the IC kind and the language
mode from the feedback slot kind. To support feedback free execution
(for V8 lite mode and lazy allocation of feedback vectors) we need to
infer the IC kind even when feedback vectors are not present.

To be able to infer the language mode without feedback vectors, this cl
forces context allocation in cases where we raise the language mode in
the middle of a function. The language mode is the stricter of the
language mode on the SFI and the language mode of the current context.

This cl updates the bytecode handlers to check for valid feedback vectors
and to call into runtime if the feedback vector is not allocated. It also
adds new runtime functions to be able to infer the IC kind when there is no
feedback vector. Most of the builtins and handlers remain unchanged because
they are only used when feedback vector is present.

Bug: v8:8394
Change-Id: I1f77740c0d68ddaa0de076597f5f6bcb2e966d70
Reviewed-on: https://chromium-review.googlesource.com/c/1358516
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58191}
parent 83544915
......@@ -2311,8 +2311,10 @@ void Scope::AllocateVariablesRecursively() {
// scope and for a function scope that makes an 'eval' call we need a context,
// even if no local variables were statically allocated in the scope.
// Likewise for modules and function scopes representing asm.js modules.
// Also force a context, if the scope is stricter than the outer scope.
bool must_have_context =
is_with_scope() || is_module_scope() || IsAsmModule() ||
ForceContextForLanguageMode() ||
(is_function_scope() && AsDeclarationScope()->calls_sloppy_eval()) ||
(is_block_scope() && is_declaration_scope() &&
AsDeclarationScope()->calls_sloppy_eval());
......
......@@ -422,12 +422,26 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
bool ContainsAsmModule() const;
// Does this scope have the potential to execute declarations non-linearly?
bool is_nonlinear() const { return scope_nonlinear_; }
// Returns if we need to force a context because the current scope is stricter
// than the outerscope. We need this to properly track the language mode using
// the context. This is required in ICs where we lookup the language mode
// from the context.
bool ForceContextForLanguageMode() const {
// For function scopes we need not force a context since the language mode
// can be obtained from the closure. Script scopes always have a context.
if (scope_type_ == FUNCTION_SCOPE || scope_type_ == SCRIPT_SCOPE) {
return false;
}
DCHECK_NOT_NULL(outer_scope_);
return (language_mode() > outer_scope_->language_mode());
}
// Whether this needs to be represented by a runtime context.
bool NeedsContext() const {
// Catch scopes always have heap slots.
DCHECK_IMPLIES(is_catch_scope(), num_heap_slots() > 0);
DCHECK_IMPLIES(is_with_scope(), num_heap_slots() > 0);
DCHECK_IMPLIES(ForceContextForLanguageMode(), num_heap_slots() > 0);
return num_heap_slots() > 0;
}
......
......@@ -9910,6 +9910,57 @@ void CodeStubAssembler::UpdateFeedback(Node* feedback, Node* maybe_vector,
BIND(&end);
}
Node* CodeStubAssembler::GetLanguageMode(
TNode<SharedFunctionInfo> shared_function_info, Node* context) {
VARIABLE(var_language_mode, MachineRepresentation::kTaggedSigned,
SmiConstant(LanguageMode::kStrict));
Label language_mode_determined(this), language_mode_sloppy(this);
// Get the language mode from SFI
TNode<Uint32T> closure_is_strict =
DecodeWord32<SharedFunctionInfo::IsStrictBit>(LoadObjectField(
shared_function_info, SharedFunctionInfo::kFlagsOffset,
MachineType::Uint32()));
// It is already strict, we need not check context's language mode.
GotoIf(closure_is_strict, &language_mode_determined);
// SFI::LanguageMode is sloppy, check if context has a stricter mode.
TNode<ScopeInfo> scope_info =
CAST(LoadObjectField(context, Context::kScopeInfoOffset));
// If no flags field assume sloppy
GotoIf(SmiLessThanOrEqual(LoadFixedArrayBaseLength(scope_info),
SmiConstant(ScopeInfo::Fields::kFlags)),
&language_mode_sloppy);
TNode<Smi> flags = CAST(LoadFixedArrayElement(
scope_info, SmiConstant(ScopeInfo::Fields::kFlags)));
TNode<Uint32T> context_is_strict =
DecodeWord32<ScopeInfo::LanguageModeField>(SmiToInt32(flags));
GotoIf(context_is_strict, &language_mode_determined);
Goto(&language_mode_sloppy);
// Both Context::ScopeInfo::LanguageMode and SFI::LanguageMode are sloppy.
BIND(&language_mode_sloppy);
var_language_mode.Bind(SmiConstant(LanguageMode::kSloppy));
Goto(&language_mode_determined);
BIND(&language_mode_determined);
return var_language_mode.value();
}
Node* CodeStubAssembler::GetLanguageMode(TNode<JSFunction> closure,
Node* context) {
TNode<SharedFunctionInfo> sfi =
CAST(LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset));
return GetLanguageMode(sfi, context);
}
Node* CodeStubAssembler::GetLanguageMode(TNode<FeedbackVector> vector,
Node* context) {
TNode<SharedFunctionInfo> sfi =
CAST(LoadObjectField(vector, FeedbackVector::kSharedFunctionInfoOffset));
return GetLanguageMode(sfi, context);
}
void CodeStubAssembler::ReportFeedbackUpdate(
SloppyTNode<FeedbackVector> feedback_vector, SloppyTNode<IntPtrT> slot_id,
const char* reason) {
......
......@@ -2700,6 +2700,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Update the type feedback vector.
void UpdateFeedback(Node* feedback, Node* feedback_vector, Node* slot_id);
// Returns the stricter of the Context::ScopeInfo::LanguageMode and
// the language mode on the SFI.
Node* GetLanguageMode(TNode<SharedFunctionInfo> sfi, Node* context);
Node* GetLanguageMode(TNode<JSFunction> closure, Node* context);
Node* GetLanguageMode(TNode<FeedbackVector> vector, Node* context);
// Report that there was a feedback update, performing any tasks that should
// be done after a feedback update.
void ReportFeedbackUpdate(SloppyTNode<FeedbackVector> feedback_vector,
......
......@@ -828,6 +828,9 @@ void AccessorAssembler::HandleStoreICNativeDataProperty(
Node* accessor_info = LoadDescriptorValue(LoadMap(holder), descriptor);
CSA_CHECK(this, IsAccessorInfo(accessor_info));
// TODO(8580): Get the language mode lazily when required to avoid the
// computation of GetLanguageMode here. Also make the computation of
// language mode not dependent on vector.
Node* language_mode = GetLanguageMode(p->vector, p->slot);
TailCallRuntime(Runtime::kStoreCallbackProperty, p->context, p->receiver,
......@@ -1448,6 +1451,9 @@ void AccessorAssembler::HandleStoreToProxy(const StoreICParameters* p,
Label if_index(this), if_unique_name(this),
to_name_failed(this, Label::kDeferred);
// TODO(8580): Get the language mode lazily when required to avoid the
// computation of GetLanguageMode here. Also make the computation of
// language mode not dependent on vector.
Node* language_mode = GetLanguageMode(p->vector, p->slot);
if (support_elements == kSupportElements) {
......@@ -2383,6 +2389,8 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p,
// accident.
Label stub_call(this, Label::kDeferred), miss(this, Label::kDeferred);
GotoIf(IsUndefined(p->vector), &miss);
// Inlined fast path.
{
Comment("LoadIC_BytecodeHandler_fast");
......@@ -2569,7 +2577,8 @@ void AccessorAssembler::LoadGlobalIC(TNode<FeedbackVector> vector, Node* slot,
TNode<Context> context = lazy_context();
TNode<Name> name = lazy_name();
exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, context, name,
ParameterToTagged(slot, slot_mode), vector);
ParameterToTagged(slot, slot_mode), vector,
SmiConstant(typeof_mode));
}
}
......@@ -3181,9 +3190,8 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
BIND(&miss);
{
Comment("StoreInArrayLiteralIC_miss");
// TODO(neis): Introduce Runtime::kStoreInArrayLiteralIC_Miss.
TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot,
p->vector, p->receiver, p->name);
TailCallRuntime(Runtime::kStoreInArrayLiteralIC_Miss, p->context, p->value,
p->slot, p->vector, p->receiver, p->name);
}
}
......
This diff is collapsed.
......@@ -19,6 +19,8 @@
namespace v8 {
namespace internal {
enum class NamedPropertyType : bool { kNotOwn, kOwn };
//
// IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
//
......@@ -35,7 +37,8 @@ class IC {
// Construct the IC structure with the given number of extra
// JavaScript frames on the stack.
IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot);
IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
FeedbackSlotKind kind);
virtual ~IC() = default;
State state() const { return state_; }
......@@ -204,8 +207,9 @@ class IC {
class LoadIC : public IC {
public:
LoadIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot)
: IC(isolate, vector, slot) {
LoadIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
FeedbackSlotKind kind)
: IC(isolate, vector, slot, kind) {
DCHECK(IsAnyLoad());
}
......@@ -239,8 +243,8 @@ class LoadIC : public IC {
class LoadGlobalIC : public LoadIC {
public:
LoadGlobalIC(Isolate* isolate, Handle<FeedbackVector> vector,
FeedbackSlot slot)
: LoadIC(isolate, vector, slot) {}
FeedbackSlot slot, FeedbackSlotKind kind)
: LoadIC(isolate, vector, slot, kind) {}
V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Name> name);
......@@ -253,8 +257,8 @@ class LoadGlobalIC : public LoadIC {
class KeyedLoadIC : public LoadIC {
public:
KeyedLoadIC(Isolate* isolate, Handle<FeedbackVector> vector,
FeedbackSlot slot)
: LoadIC(isolate, vector, slot) {}
FeedbackSlot slot, FeedbackSlotKind kind)
: LoadIC(isolate, vector, slot, kind) {}
V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Object> object,
Handle<Object> key);
......@@ -283,12 +287,13 @@ class KeyedLoadIC : public LoadIC {
class StoreIC : public IC {
public:
StoreIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot)
: IC(isolate, vector, slot) {
StoreIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
FeedbackSlotKind kind, LanguageMode language_mode)
: IC(isolate, vector, slot, kind), language_mode_(language_mode) {
DCHECK(IsAnyStore());
}
LanguageMode language_mode() const { return nexus()->GetLanguageMode(); }
LanguageMode language_mode() const { return language_mode_; }
V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(
Handle<Object> object, Handle<Name> name, Handle<Object> value,
......@@ -309,6 +314,11 @@ class StoreIC : public IC {
void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
StoreOrigin store_origin);
// TODO(v8:8580): Instead of storing the language mode, compute it lazily
// from the closure and context when needed. We only need it when throwing
// exceptions, so it is OK to be slow.
LanguageMode language_mode_;
private:
MaybeObjectHandle ComputeHandler(LookupIterator* lookup);
......@@ -318,8 +328,9 @@ class StoreIC : public IC {
class StoreGlobalIC : public StoreIC {
public:
StoreGlobalIC(Isolate* isolate, Handle<FeedbackVector> vector,
FeedbackSlot slot)
: StoreIC(isolate, vector, slot) {}
FeedbackSlot slot, FeedbackSlotKind kind,
LanguageMode language_mode)
: StoreIC(isolate, vector, slot, kind, language_mode) {}
V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(Handle<Name> name,
Handle<Object> value);
......@@ -343,8 +354,9 @@ class KeyedStoreIC : public StoreIC {
}
KeyedStoreIC(Isolate* isolate, Handle<FeedbackVector> vector,
FeedbackSlot slot)
: StoreIC(isolate, vector, slot) {}
FeedbackSlot slot, FeedbackSlotKind kind,
LanguageMode language_mode)
: StoreIC(isolate, vector, slot, kind, language_mode) {}
V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(Handle<Object> object,
Handle<Object> name,
......@@ -377,7 +389,9 @@ class StoreInArrayLiteralIC : public KeyedStoreIC {
public:
StoreInArrayLiteralIC(Isolate* isolate, Handle<FeedbackVector> vector,
FeedbackSlot slot)
: KeyedStoreIC(isolate, vector, slot) {
: KeyedStoreIC(isolate, vector, slot,
FeedbackSlotKind::kStoreInArrayLiteral,
LanguageMode::kStrict) {
DCHECK(IsStoreInArrayLiteralICKind(kind()));
}
......
This diff is collapsed.
......@@ -179,7 +179,8 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
HasSimpleParametersField::encode(has_simple_parameters) |
FunctionKindField::encode(function_kind) |
HasOuterScopeInfoField::encode(has_outer_scope_info) |
IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope());
IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope()) |
ForceContextAllocationField::encode(scope->ForceContextForLanguageMode());
scope_info->SetFlags(flags);
scope_info->SetParameterCount(parameter_count);
......@@ -482,7 +483,9 @@ int ScopeInfo::ContextLength() const {
int context_locals = ContextLocalCount();
bool function_name_context_slot =
FunctionVariableField::decode(Flags()) == CONTEXT;
bool has_context = context_locals > 0 || function_name_context_slot ||
bool force_context = ForceContextAllocationField::decode(Flags());
bool has_context = context_locals > 0 || force_context ||
function_name_context_slot ||
scope_type() == WITH_SCOPE ||
(scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
is_declaration_scope()) ||
......
......@@ -201,13 +201,52 @@ class ScopeInfo : public FixedArray {
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS
enum {
enum Fields {
#define DECL_INDEX(name) k##name,
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
#undef DECL_INDEX
kVariablePartIndex
};
// Used for the function name variable for named function expressions, and for
// the receiver.
enum VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED };
// Properties of scopes.
class ScopeTypeField : public BitField<ScopeType, 0, 4> {};
class CallsSloppyEvalField : public BitField<bool, ScopeTypeField::kNext, 1> {
};
STATIC_ASSERT(LanguageModeSize == 2);
class LanguageModeField
: public BitField<LanguageMode, CallsSloppyEvalField::kNext, 1> {};
class DeclarationScopeField
: public BitField<bool, LanguageModeField::kNext, 1> {};
class ReceiverVariableField
: public BitField<VariableAllocationInfo, DeclarationScopeField::kNext,
2> {};
class HasNewTargetField
: public BitField<bool, ReceiverVariableField::kNext, 1> {};
class FunctionVariableField
: public BitField<VariableAllocationInfo, HasNewTargetField::kNext, 2> {};
// TODO(cbruni): Combine with function variable field when only storing the
// function name.
class HasInferredFunctionNameField
: public BitField<bool, FunctionVariableField::kNext, 1> {};
class AsmModuleField
: public BitField<bool, HasInferredFunctionNameField::kNext, 1> {};
class HasSimpleParametersField
: public BitField<bool, AsmModuleField::kNext, 1> {};
class FunctionKindField
: public BitField<FunctionKind, HasSimpleParametersField::kNext, 5> {};
class HasOuterScopeInfoField
: public BitField<bool, FunctionKindField::kNext, 1> {};
class IsDebugEvaluateScopeField
: public BitField<bool, HasOuterScopeInfoField::kNext, 1> {};
class ForceContextAllocationField
: public BitField<bool, IsDebugEvaluateScopeField::kNext, 1> {};
STATIC_ASSERT(kLastFunctionKind <= FunctionKindField::kMax);
private:
// The layout of the variable part of a ScopeInfo is as follows:
// 1. ContextLocalNames:
......@@ -267,46 +306,9 @@ class ScopeInfo : public FixedArray {
InitializationFlag* init_flag = nullptr,
MaybeAssignedFlag* maybe_assigned_flag = nullptr);
// Used for the function name variable for named function expressions, and for
// the receiver.
enum VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED };
static const int kFunctionNameEntries = 2;
static const int kPositionInfoEntries = 2;
// Properties of scopes.
class ScopeTypeField : public BitField<ScopeType, 0, 4> {};
class CallsSloppyEvalField : public BitField<bool, ScopeTypeField::kNext, 1> {
};
STATIC_ASSERT(LanguageModeSize == 2);
class LanguageModeField
: public BitField<LanguageMode, CallsSloppyEvalField::kNext, 1> {};
class DeclarationScopeField
: public BitField<bool, LanguageModeField::kNext, 1> {};
class ReceiverVariableField
: public BitField<VariableAllocationInfo, DeclarationScopeField::kNext,
2> {};
class HasNewTargetField
: public BitField<bool, ReceiverVariableField::kNext, 1> {};
class FunctionVariableField
: public BitField<VariableAllocationInfo, HasNewTargetField::kNext, 2> {};
// TODO(cbruni): Combine with function variable field when only storing the
// function name.
class HasInferredFunctionNameField
: public BitField<bool, FunctionVariableField::kNext, 1> {};
class AsmModuleField
: public BitField<bool, HasInferredFunctionNameField::kNext, 1> {};
class HasSimpleParametersField
: public BitField<bool, AsmModuleField::kNext, 1> {};
class FunctionKindField
: public BitField<FunctionKind, HasSimpleParametersField::kNext, 5> {};
class HasOuterScopeInfoField
: public BitField<bool, FunctionKindField::kNext, 1> {};
class IsDebugEvaluateScopeField
: public BitField<bool, HasOuterScopeInfoField::kNext, 1> {};
STATIC_ASSERT(kLastFunctionKind <= FunctionKindField::kMax);
// Properties of variables.
class VariableModeField : public BitField<VariableMode, 0, 3> {};
class InitFlagField : public BitField<InitializationFlag, 3, 1> {};
......
......@@ -552,18 +552,22 @@ namespace internal {
F(ElementsTransitionAndStoreIC_Miss, 6, 1) \
F(KeyedLoadIC_Miss, 4, 1) \
F(KeyedStoreIC_Miss, 5, 1) \
F(KeyedStoreICNoFeedback_Miss, 4, 1) \
F(StoreInArrayLiteralIC_Miss, 5, 1) \
F(KeyedStoreIC_Slow, 5, 1) \
F(LoadAccessorProperty, 4, 1) \
F(LoadCallbackProperty, 4, 1) \
F(LoadElementWithInterceptor, 2, 1) \
F(LoadGlobalIC_Miss, 3, 1) \
F(LoadGlobalIC_Miss, 4, 1) \
F(LoadGlobalIC_Slow, 3, 1) \
F(LoadIC_Miss, 4, 1) \
F(LoadPropertyWithInterceptor, 5, 1) \
F(StoreCallbackProperty, 6, 1) \
F(StoreGlobalIC_Miss, 4, 1) \
F(StoreGlobalICNoFeedback_Miss, 3, 1) \
F(StoreGlobalIC_Slow, 5, 1) \
F(StoreIC_Miss, 5, 1) \
F(StoreICNoFeedback_Miss, 5, 1) \
F(StoreInArrayLiteralIC_Slow, 5, 1) \
F(StorePropertyWithInterceptor, 5, 1) \
F(CloneObjectIC_Miss, 4, 1)
......
......@@ -12,28 +12,32 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); }
}
"
frame size: 7
frame size: 8
parameter count: 1
bytecode array length: 38
bytecode array length: 44
bytecodes: [
/* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(5),
B(CreateClosure), U8(1), U8(0), U8(2),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(CreateClosure), U8(2), U8(1), U8(2),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3),
B(Mov), R(4), R(0),
B(LdaConstant), U8(1),
B(Star), R(4),
B(CreateClosure), U8(3), U8(1), U8(2),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(Mov), R(5), R(0),
B(PopContext), R(2),
B(Mov), R(0), R(1),
B(LdaUndefined),
/* 149 S> */ B(Return),
]
constant pool: [
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
......@@ -48,28 +52,32 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); }
}
"
frame size: 7
frame size: 8
parameter count: 1
bytecode array length: 38
bytecode array length: 44
bytecodes: [
/* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(5),
B(CreateClosure), U8(1), U8(0), U8(2),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(CreateClosure), U8(2), U8(1), U8(2),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3),
B(Mov), R(4), R(0),
B(LdaConstant), U8(1),
B(Star), R(4),
B(CreateClosure), U8(3), U8(1), U8(2),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(Mov), R(5), R(0),
B(PopContext), R(2),
B(Mov), R(0), R(1),
B(LdaUndefined),
/* 149 S> */ B(Return),
]
constant pool: [
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
......@@ -86,9 +94,9 @@ snippet: "
static [n1]() { return n1; }
}
"
frame size: 11
frame size: 12
parameter count: 1
bytecode array length: 77
bytecode array length: 87
bytecodes: [
B(CreateFunctionContext), U8(0), U8(2),
B(PushContext), R(2),
......@@ -97,28 +105,31 @@ bytecodes: [
/* 43 E> */ B(StaCurrentContextSlot), U8(4),
/* 57 S> */ B(LdaConstant), U8(2),
/* 57 E> */ B(StaCurrentContextSlot), U8(5),
B(CreateBlockContext), U8(3),
B(PushContext), R(3),
B(LdaTheHole),
B(Star), R(6),
B(CreateClosure), U8(4), U8(0), U8(2),
B(Star), R(3),
B(LdaConstant), U8(3),
B(Star), R(7),
B(CreateClosure), U8(5), U8(0), U8(2),
B(Star), R(4),
/* 75 S> */ B(LdaImmutableCurrentContextSlot), U8(4),
B(ToName), R(7),
B(CreateClosure), U8(5), U8(1), U8(2),
B(Star), R(8),
/* 106 S> */ B(LdaImmutableCurrentContextSlot), U8(5),
B(ToName), R(9),
B(LdaConstant), U8(6),
B(TestEqualStrict), R(9), U8(2),
B(Mov), R(3), R(5),
B(LdaConstant), U8(4),
B(Star), R(5),
/* 75 S> */ B(LdaImmutableContextSlot), R(3), U8(4), U8(0),
B(ToName), R(8),
B(CreateClosure), U8(6), U8(1), U8(2),
B(Star), R(9),
/* 106 S> */ B(LdaImmutableContextSlot), R(3), U8(5), U8(0),
B(ToName), R(10),
B(LdaConstant), U8(7),
B(TestEqualStrict), R(10), U8(2),
B(Mov), R(4), R(6),
B(JumpIfFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
B(CreateClosure), U8(7), U8(3), U8(2),
B(Star), R(10),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(7),
B(Star), R(4),
B(Mov), R(3), R(0),
B(CreateClosure), U8(8), U8(3), U8(2),
B(Star), R(11),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(7),
B(Star), R(5),
B(Mov), R(4), R(0),
B(PopContext), R(3),
B(Mov), R(0), R(1),
B(LdaUndefined),
/* 129 S> */ B(Return),
......@@ -127,6 +138,7 @@ constant pool: [
SCOPE_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["b"],
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
......@@ -142,31 +154,35 @@ snippet: "
class C { constructor() { count++; }}
return new C();
"
frame size: 7
frame size: 8
parameter count: 1
bytecode array length: 46
bytecode array length: 52
bytecodes: [
B(CreateFunctionContext), U8(0), U8(1),
B(PushContext), R(2),
/* 30 E> */ B(StackCheck),
/* 46 S> */ B(LdaZero),
/* 46 E> */ B(StaCurrentContextSlot), U8(4),
B(CreateBlockContext), U8(1),
B(PushContext), R(3),
B(LdaTheHole),
B(Star), R(6),
B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3),
B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(7),
B(CreateClosure), U8(3), U8(0), U8(2),
B(Star), R(4),
B(Mov), R(5), R(0),
B(LdaConstant), U8(2),
B(Star), R(5),
B(Mov), R(4), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(3),
B(Star), R(5),
B(Mov), R(6), R(0),
B(PopContext), R(3),
B(Mov), R(0), R(1),
/* 87 S> */ B(Ldar), R(1),
/* 94 E> */ B(Construct), R(3), R(0), U8(0), U8(1),
/* 94 E> */ B(Construct), R(1), R(0), U8(0), U8(1),
/* 102 S> */ B(Return),
]
constant pool: [
SCOPE_INFO_TYPE,
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
......@@ -179,39 +195,47 @@ snippet: "
(class {})
class E { static name () {}}
"
frame size: 7
frame size: 8
parameter count: 1
bytecode array length: 61
bytecode array length: 73
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaTheHole),
B(Star), R(5),
B(CreateClosure), U8(1), U8(0), U8(2),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(3),
/* 34 S> */ B(CreateBlockContext), U8(0),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(5),
B(CreateClosure), U8(3), U8(1), U8(2),
B(Star), R(2),
B(LdaConstant), U8(2),
B(Star), R(6),
B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3),
B(CreateClosure), U8(4), U8(2), U8(2),
B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(PopContext), R(2),
B(CreateBlockContext), U8(3),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(CreateClosure), U8(5), U8(1), U8(2),
B(Star), R(3),
B(Mov), R(4), R(0),
B(LdaConstant), U8(4),
B(Star), R(4),
B(CreateClosure), U8(6), U8(2), U8(2),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(Mov), R(5), R(0),
B(PopContext), R(2),
B(Mov), R(0), R(1),
B(LdaUndefined),
/* 74 S> */ B(Return),
]
constant pool: [
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
......
......@@ -10,30 +10,34 @@ snippet: "
class A { constructor(...args) { this.args = args; } }
new A(...[1, 2, 3]);
"
frame size: 6
frame size: 7
parameter count: 1
bytecode array length: 45
bytecode array length: 51
bytecodes: [
/* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(5),
B(CreateClosure), U8(1), U8(0), U8(2),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(6),
B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3),
B(Mov), R(4), R(0),
B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(Mov), R(5), R(0),
B(PopContext), R(2),
B(Mov), R(0), R(1),
/* 89 S> */ B(CreateArrayLiteral), U8(2), U8(1), U8(37),
/* 89 S> */ B(CreateArrayLiteral), U8(3), U8(1), U8(37),
B(Star), R(3),
B(Ldar), R(1),
/* 89 E> */ B(ConstructWithSpread), R(2), R(3), U8(1), U8(2),
/* 89 E> */ B(ConstructWithSpread), R(1), R(3), U8(1), U8(2),
B(LdaUndefined),
/* 110 S> */ B(Return),
]
constant pool: [
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
......@@ -46,32 +50,36 @@ snippet: "
class A { constructor(...args) { this.args = args; } }
new A(0, ...[1, 2, 3]);
"
frame size: 6
frame size: 7
parameter count: 1
bytecode array length: 48
bytecode array length: 54
bytecodes: [
/* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(5),
B(CreateClosure), U8(1), U8(0), U8(2),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(6),
B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3),
B(Mov), R(4), R(0),
B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(Mov), R(5), R(0),
B(PopContext), R(2),
B(Mov), R(0), R(1),
/* 89 S> */ B(LdaZero),
B(Star), R(3),
B(CreateArrayLiteral), U8(2), U8(1), U8(37),
B(CreateArrayLiteral), U8(3), U8(1), U8(37),
B(Star), R(4),
B(Ldar), R(1),
/* 89 E> */ B(ConstructWithSpread), R(2), R(3), U8(2), U8(2),
/* 89 E> */ B(ConstructWithSpread), R(1), R(3), U8(2), U8(2),
B(LdaUndefined),
/* 113 S> */ B(Return),
]
constant pool: [
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
......@@ -86,41 +94,45 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 124
bytecode array length: 133
bytecodes: [
/* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(5),
B(CreateClosure), U8(1), U8(0), U8(2),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(6),
B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3),
B(Mov), R(4), R(0),
B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(Mov), R(5), R(0),
B(PopContext), R(2),
B(Mov), R(0), R(1),
/* 89 S> */ B(CreateArrayLiteral), U8(2), U8(1), U8(37),
/* 89 S> */ B(CreateArrayLiteral), U8(3), U8(1), U8(37),
B(Star), R(4),
B(LdaConstant), U8(3),
B(LdaConstant), U8(4),
B(Star), R(3),
/* 101 S> */ B(CreateArrayLiteral), U8(4), U8(5), U8(37),
/* 101 S> */ B(CreateArrayLiteral), U8(5), U8(5), U8(37),
B(Star), R(8),
B(LdaNamedProperty), R(8), U8(5), U8(6),
B(LdaNamedProperty), R(8), U8(6), U8(6),
B(Star), R(9),
B(CallProperty0), R(9), R(8), U8(8),
B(Mov), R(5), R(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(7),
B(LdaNamedProperty), R(7), U8(6), U8(10),
B(LdaNamedProperty), R(7), U8(7), U8(10),
B(Star), R(6),
B(CallProperty0), R(6), R(7), U8(12),
B(Star), R(5),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(5), U8(1),
B(LdaNamedProperty), R(5), U8(7), U8(14),
B(LdaNamedProperty), R(5), U8(8), U8(14),
B(JumpIfToBooleanTrue), U8(21),
B(LdaNamedProperty), R(5), U8(8), U8(16),
B(LdaNamedProperty), R(5), U8(9), U8(16),
B(Star), R(5),
B(StaInArrayLiteral), R(4), R(3), U8(3),
B(Ldar), R(3),
......@@ -135,6 +147,7 @@ bytecodes: [
/* 116 S> */ B(Return),
]
constant pool: [
SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
......
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