blob: 37dc976f03d40c02966a317a6f827e5af26a61e1 [file] [log] [blame]
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@abstract
// We normally don't generate a BodyDescriptor for an abstact class, but here we
// do since all context classes share the same BodyDescriptor.
@generateBodyDescriptor
extern class Context extends HeapObject {
macro GetScopeInfo(): ScopeInfo {
return *ContextSlot(this, ContextSlot::SCOPE_INFO_INDEX);
}
const length: Smi;
elements[length]: Object;
}
@cppObjectDefinition
extern class ScriptContextTable extends HeapObject {
const capacity: Smi;
length: Smi;
names_to_context_index: NameToIndexHashTable;
objects[capacity]: Context;
}
extern class AwaitContext extends Context generates 'TNode<Context>';
extern class BlockContext extends Context generates 'TNode<Context>';
extern class CatchContext extends Context generates 'TNode<Context>';
extern class DebugEvaluateContext extends Context
generates 'TNode<Context>';
extern class EvalContext extends Context generates 'TNode<Context>';
extern class ModuleContext extends Context generates 'TNode<Context>';
extern class ScriptContext extends Context generates 'TNode<Context>';
extern class WithContext extends Context generates 'TNode<Context>';
extern class FunctionContext extends Context generates 'TNode<Context>';
const kInitialContextSlotValue: Smi = 0;
@export
macro AllocateSyntheticFunctionContext(
nativeContext: NativeContext, slots: constexpr int31): FunctionContext {
return AllocateSyntheticFunctionContext(
nativeContext, Convert<intptr>(slots));
}
macro AllocateSyntheticFunctionContext(
nativeContext: NativeContext, slots: intptr): FunctionContext {
static_assert(slots >= ContextSlot::MIN_CONTEXT_SLOTS);
const map =
*ContextSlot(nativeContext, ContextSlot::FUNCTION_CONTEXT_MAP_INDEX);
const result = new FunctionContext{
map,
length: Convert<Smi>(slots),
elements: ...ConstantIterator<Smi>(kInitialContextSlotValue)
};
InitContextSlot(result, ContextSlot::SCOPE_INFO_INDEX, kEmptyScopeInfo);
InitContextSlot(result, ContextSlot::PREVIOUS_INDEX, Undefined);
return result;
}
extern class NativeContext extends Context;
type Slot<Container : type extends Context, T : type extends Object> extends
intptr;
// We cannot use ContextSlot() for initialization since that one asserts the
// slot has the right type already.
macro InitContextSlot<
ArgumentContext: type, AnnotatedContext: type, T: type, U: type>(
context: ArgumentContext, index: Slot<AnnotatedContext, T>,
value: U): void {
// Make sure the arguments have the right type.
const context: AnnotatedContext = context;
const value: T = value;
dcheck(TaggedEqual(context.elements[index], kInitialContextSlotValue));
context.elements[index] = value;
}
macro ContextSlot<ArgumentContext: type, AnnotatedContext: type, T: type>(
context: ArgumentContext, index: Slot<AnnotatedContext, T>):&T {
const context: AnnotatedContext = context;
return torque_internal::unsafe::ReferenceCast<T>(&context.elements[index]);
}
macro NativeContextSlot<T: type>(
context: NativeContext, index: Slot<NativeContext, T>):&T {
return ContextSlot(context, index);
}
macro NativeContextSlot<T: type>(
context: Context, index: Slot<NativeContext, T>):&T {
return ContextSlot(LoadNativeContext(context), index);
}
macro NativeContextSlot<C: type, T: type>(
implicit context: C)(index: Slot<NativeContext, T>):&T {
return NativeContextSlot(context, index);
}
extern enum ContextSlot extends intptr constexpr 'Context::Field' {
SCOPE_INFO_INDEX: Slot<Context, ScopeInfo>,
// Zero is used for the NativeContext, Undefined is used for synthetic
// function contexts.
PREVIOUS_INDEX: Slot<Context, Context|Zero|Undefined>,
AGGREGATE_ERROR_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
ARRAY_BUFFER_FUN_INDEX: Slot<NativeContext, Constructor>,
ARRAY_BUFFER_NOINIT_FUN_INDEX: Slot<NativeContext, JSFunction>,
ARRAY_BUFFER_MAP_INDEX: Slot<NativeContext, Map>,
ARRAY_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
ARRAY_JOIN_STACK_INDEX: Slot<NativeContext, Undefined|FixedArray>,
OBJECT_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
ITERATOR_RESULT_MAP_INDEX: Slot<NativeContext, Map>,
ITERATOR_MAP_HELPER_MAP_INDEX: Slot<NativeContext, Map>,
ITERATOR_FILTER_HELPER_MAP_INDEX: Slot<NativeContext, Map>,
ITERATOR_TAKE_HELPER_MAP_INDEX: Slot<NativeContext, Map>,
ITERATOR_DROP_HELPER_MAP_INDEX: Slot<NativeContext, Map>,
ITERATOR_FLAT_MAP_HELPER_MAP_INDEX: Slot<NativeContext, Map>,
ITERATOR_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
VALID_ITERATOR_WRAPPER_MAP_INDEX: Slot<NativeContext, Map>,
JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX: Slot<NativeContext, Map>,
JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX: Slot<NativeContext, Map>,
JS_MAP_MAP_INDEX: Slot<NativeContext, Map>,
JS_SET_MAP_INDEX: Slot<NativeContext, Map>,
MATH_RANDOM_CACHE_INDEX: Slot<NativeContext, FixedDoubleArray>,
MATH_RANDOM_INDEX_INDEX: Slot<NativeContext, Smi>,
NUMBER_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
PROXY_REVOCABLE_RESULT_MAP_INDEX: Slot<NativeContext, Map>,
REFLECT_APPLY_INDEX: Slot<NativeContext, Callable>,
REGEXP_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
REGEXP_LAST_MATCH_INFO_INDEX: Slot<NativeContext, RegExpMatchInfo>,
INITIAL_STRING_ITERATOR_MAP_INDEX: Slot<NativeContext, Map>,
INITIAL_ARRAY_ITERATOR_MAP_INDEX: Slot<NativeContext, Map>,
INITIAL_ITERATOR_PROTOTYPE_INDEX: Slot<NativeContext, JSObject>,
SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP: Slot<NativeContext, Map>,
STRICT_ARGUMENTS_MAP_INDEX: Slot<NativeContext, Map>,
SLOPPY_ARGUMENTS_MAP_INDEX: Slot<NativeContext, Map>,
FAST_ALIASED_ARGUMENTS_MAP_INDEX: Slot<NativeContext, Map>,
FUNCTION_CONTEXT_MAP_INDEX: Slot<NativeContext, Map>,
FUNCTION_PROTOTYPE_APPLY_INDEX: Slot<NativeContext, JSFunction>,
UINT8_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
INT8_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
UINT16_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
INT16_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
UINT32_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
INT32_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
FLOAT16_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
FLOAT32_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
FLOAT64_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
UINT8_CLAMPED_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
BIGUINT64_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
BIGINT64_ARRAY_FUN_INDEX: Slot<NativeContext, JSFunction>,
RAB_GSAB_UINT8_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_INT8_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_UINT16_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_INT16_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_UINT32_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_INT32_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_FLOAT16_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_FLOAT32_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_FLOAT64_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_UINT8_CLAMPED_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_BIGUINT64_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
RAB_GSAB_BIGINT64_ARRAY_MAP_INDEX: Slot<NativeContext, Map>,
ACCESSOR_PROPERTY_DESCRIPTOR_MAP_INDEX: Slot<NativeContext, Map>,
DATA_PROPERTY_DESCRIPTOR_MAP_INDEX: Slot<NativeContext, Map>,
PROMISE_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
PROMISE_THEN_INDEX: Slot<NativeContext, JSFunction>,
PROMISE_PROTOTYPE_INDEX: Slot<NativeContext, JSObject>,
STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX: Slot<NativeContext, Map>,
PROMISE_HOOK_INIT_FUNCTION_INDEX: Slot<NativeContext, Undefined|Callable>,
PROMISE_HOOK_BEFORE_FUNCTION_INDEX: Slot<NativeContext, Undefined|Callable>,
PROMISE_HOOK_AFTER_FUNCTION_INDEX: Slot<NativeContext, Undefined|Callable>,
PROMISE_HOOK_RESOLVE_FUNCTION_INDEX: Slot<NativeContext, Undefined|Callable>,
// @if(V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA)
CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX: Slot<NativeContext, HeapObject>,
BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX: Slot<NativeContext, Map>,
BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX: Slot<NativeContext, Map>,
WRAPPED_FUNCTION_MAP_INDEX: Slot<NativeContext, Map>,
@sameEnumValueAs(MIN_CONTEXT_SLOTS)
CONST_TRACKING_LET_SIDE_DATA_INDEX: Slot<Context, HeapObject>,
MIN_CONTEXT_SLOTS,
MIN_CONTEXT_EXTENDED_SLOTS,
...
}
@export
macro LoadContextElement(c: Context, i: intptr): Object {
return c.elements[i];
}
@export
macro LoadContextElement(c: Context, i: Smi): Object {
return c.elements[i];
}
@export
macro LoadContextElement(c: Context, i: constexpr int32): Object {
return c.elements[i];
}
@export
macro StoreContextElement(c: Context, i: intptr, o: Object): void {
c.elements[i] = o;
}
@export
macro StoreContextElement(c: Context, i: Smi, o: Object): void {
c.elements[i] = o;
}
@export
macro StoreContextElement(c: Context, i: constexpr int32, o: Object): void {
c.elements[i] = o;
}
@export
macro StoreContextElementAndUpdateSideData(
c: Context, i: intptr, o: Object): void {
UpdateConstTrackingLetSideData(c, i, o);
c.elements[i] = o;
}
@export
macro StoreContextElementAndUpdateSideData(
c: Context, i: constexpr int32, o: Object): void {
UpdateConstTrackingLetSideData(c, i, o);
c.elements[i] = o;
}
builtin StoreCurrentScriptContextSlotBaseline(o: Object, i: Smi): JSAny {
const context = internal::LoadContextFromBaseline();
const index = SmiUntag(i);
UpdateConstTrackingLetSideData(context, index, o);
context.elements[index] = o;
return Undefined;
}
builtin StoreScriptContextSlotBaseline(
c: Object, o: Object, i: Smi, d: TaggedIndex): JSAny {
let context = UnsafeCast<Context>(c);
let depth = TaggedIndexToIntPtr(d);
while (depth > 0) {
--depth;
context =
UnsafeCast<Context>(context.elements[ContextSlot::PREVIOUS_INDEX]);
}
const index = SmiUntag(i);
UpdateConstTrackingLetSideData(context, index, o);
context.elements[index] = o;
return Undefined;
}
namespace runtime {
extern runtime InvalidateDependentCodeForConstTrackingLet(Context, Object):
JSAny;
} // namespace runtime
macro UpdateConstTrackingLetSideData(
c: Context, index: intptr, newValue: Object): void {
const scriptContext = Cast<ScriptContext>(c) otherwise unreachable;
const sideDataIndex = index - ContextSlot::MIN_CONTEXT_EXTENDED_SLOTS;
const sideData: Object = *ContextSlot(
scriptContext, ContextSlot::CONST_TRACKING_LET_SIDE_DATA_INDEX);
const sideDataFixedArray: FixedArray =
Cast<FixedArray>(sideData) otherwise return;
if (sideDataFixedArray.length == 0) {
// No side data (maybe the const tracking let flag is not on).
return;
}
const oldValue = c.elements[index];
if (oldValue == TheHole) {
// Setting the initial value.
dcheck(sideDataFixedArray.objects[sideDataIndex] == Undefined);
sideDataFixedArray.objects[sideDataIndex] =
kConstTrackingLetCellConstMarker;
return;
}
if (TaggedEqual(oldValue, newValue)) {
return;
}
// From now on, we know the value is no longer a constant. If there's a
// DependentCode, invalidate it.
const data = sideDataFixedArray.objects[sideDataIndex];
typeswitch (data) {
case (_s: Smi): {
// The value is not constant after this write, but it also was not used as
// a constant (there's no code to invalidate). No action needed here; the
// side data will be updated below.
}
case (cell: ConstTrackingLetCell): {
runtime::InvalidateDependentCodeForConstTrackingLet(c, cell);
}
case (Object): {
// If this is reached, there's a code path which initializes or assigns a
// top-level `let` variable but doesn't update the side data.
unreachable;
}
}
sideDataFixedArray.objects[sideDataIndex] =
kConstTrackingLetCellNonConstMarker;
}
// A dummy used instead of a context constant for runtime calls that don't need
// a context.
type NoContext extends Smi;
extern macro NoContextConstant(): NoContext;
const kNoContext: NoContext = NoContextConstant();