blob: e24eefe6312888d7356a3c04ff00437cbb73f34f [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.
@generateCppClass
extern class JSArgumentsObject extends JSObject {
}
type JSArgumentsObjectWithLength =
JSSloppyArgumentsObject|JSStrictArgumentsObject;
@export
macro IsJSArgumentsObjectWithLength(implicit context: Context)(o: Object):
bool {
return Is<JSArgumentsObjectWithLength>(o);
}
// Just a starting shape for JSObject; properties can move after initialization.
extern shape JSSloppyArgumentsObject extends JSArgumentsObject {
length: JSAny;
callee: JSAny;
}
// Just a starting shape for JSObject; properties can move after initialization.
extern shape JSStrictArgumentsObject extends JSArgumentsObject {
length: JSAny;
}
type SloppyArgumentsElements extends FixedArray;
@generateCppClass
extern class AliasedArgumentsEntry extends Struct {
aliased_context_slot: Smi;
}
// TODO(danno): This should be a namespace {} once supported
namespace arguments {
macro NewJSStrictArgumentsObject(implicit context: Context)(
elements: FixedArray): JSStrictArgumentsObject {
const map = GetStrictArgumentsMap();
return new JSStrictArgumentsObject{
map,
properties_or_hash: kEmptyFixedArray,
elements,
length: elements.length
};
}
macro NewJSSloppyArgumentsObject(implicit context: Context)(
elements: FixedArray, callee: JSFunction): JSSloppyArgumentsObject {
const map = GetSloppyArgumentsMap();
return new JSSloppyArgumentsObject{
map,
properties_or_hash: kEmptyFixedArray,
elements,
length: elements.length,
callee
};
}
macro NewJSFastAliasedArgumentsObject(implicit context: Context)(
elements: FixedArray, length: Smi,
callee: JSFunction): JSSloppyArgumentsObject {
// TODO(danno): FastAliasedArguments should really be a type for itself
const map = GetFastAliasedArgumentsMap();
return new JSSloppyArgumentsObject{
map,
properties_or_hash: kEmptyFixedArray,
elements,
length,
callee
};
}
struct ParameterMapIterator {
macro Next(): Object labels NoMore {
const currentMapSlotCopy = this.currentMapSlot++;
if (currentMapSlotCopy > 1) {
if (this.currentIndex == this.endInterationIndex) goto NoMore;
this.currentIndex--;
return Convert<Smi>(this.currentIndex);
} else if (currentMapSlotCopy == 0) {
return this.context;
} else {
assert(currentMapSlotCopy == 1);
return this.elements;
}
}
const context: Context;
const elements: FixedArray;
currentIndex: intptr;
const endInterationIndex: intptr;
currentMapSlot: intptr;
}
macro NewParameterMapIterator(
context: Context, elements: FixedArray, formalParameterCount: intptr,
mappedCount: intptr): ParameterMapIterator {
const flags = context.scope_info.flags;
let contextHeaderSize: intptr = MIN_CONTEXT_SLOTS;
if (flags.has_context_extension_slot) ++contextHeaderSize;
// Copy the parameter slots and the holes in the arguments.
// We need to fill in mapped_count slots. They index the context,
// where parameters are stored in reverse order, at
// context_header_size .. context_header_size+argument_count-1
// The mapped parameter thus need to get indices
// context_header_size+parameter_count-1 ..
// context_header_size+argument_count-mapped_count
// We loop from right to left.
const afterLastContextIndex = contextHeaderSize + formalParameterCount;
const firstContextIndex = afterLastContextIndex - mappedCount;
return ParameterMapIterator{
context,
elements,
currentIndex: afterLastContextIndex,
endInterationIndex: firstContextIndex,
currentMapSlot: 0
};
}
struct ParameterValueIterator {
macro Next(): Object labels NoMore() {
if (this.mapped_count != 0) {
this.mapped_count--;
return TheHole;
}
if (this.current == this.arguments.length) goto NoMore;
return this.arguments[this.current++];
}
mapped_count: intptr;
const arguments: Arguments;
current: intptr;
}
macro NewParameterValueIterator(mappedCount: intptr, arguments: Arguments):
ParameterValueIterator {
return ParameterValueIterator{
mapped_count: mappedCount,
arguments,
current: mappedCount
};
}
macro NewAllArguments(implicit context: Context)(
frame: FrameWithArguments, argumentCount: intptr): JSArray {
const map = GetFastPackedElementsJSArrayMap();
const arguments = GetFrameArguments(frame, argumentCount);
const it = ArgumentsIterator{arguments, current: 0};
const elements = NewFixedArray(argumentCount, it);
return NewJSArray(map, elements);
}
macro NewRestArguments(implicit context:
Context)(info: FrameWithArgumentsInfo): JSArray {
const argumentCount = Convert<intptr>(info.argument_count);
const formalParameterCount = Convert<intptr>(info.formal_parameter_count);
const map = GetFastPackedElementsJSArrayMap();
const length = (formalParameterCount >= argumentCount) ?
0 :
argumentCount - formalParameterCount;
const arguments = GetFrameArguments(info.frame, argumentCount);
const it = ArgumentsIterator{arguments, current: formalParameterCount};
const elements = NewFixedArray(length, it);
return NewJSArray(map, elements);
}
macro NewStrictArguments(implicit context: Context)(
info: FrameWithArgumentsInfo): JSStrictArgumentsObject {
const argumentCount = Convert<intptr>(info.argument_count);
const arguments = GetFrameArguments(info.frame, argumentCount);
const it = ArgumentsIterator{arguments, current: 0};
const elements = NewFixedArray(argumentCount, it);
return NewJSStrictArgumentsObject(elements);
}
macro NewSloppyArguments(implicit context: Context)(
info: FrameWithArgumentsInfo,
callee: JSFunction): JSSloppyArgumentsObject {
const argumentCount = Convert<intptr>(info.argument_count);
const arguments = GetFrameArguments(info.frame, argumentCount);
const formalParameterCount = Convert<intptr>(info.formal_parameter_count);
if (formalParameterCount == 0) {
const it = ArgumentsIterator{arguments, current: 0};
const elements = NewFixedArray(argumentCount, it);
return NewJSSloppyArgumentsObject(elements, callee);
}
const mappedCount = IntPtrMin(formalParameterCount, argumentCount);
const it = NewParameterValueIterator(mappedCount, arguments);
const parameterValues = NewFixedArray(argumentCount, it);
let paramIter = NewParameterMapIterator(
context, parameterValues, formalParameterCount, mappedCount);
const elementsLength =
Convert<Smi>(mappedCount + kSloppyArgumentsParameterMapStart);
const map = kSloppyArgumentsElementsMap;
const elements = new
FixedArray{map, length: elementsLength, objects: ...paramIter};
const length = Convert<Smi>(argumentCount);
return NewJSFastAliasedArgumentsObject(elements, length, callee);
}
}
@export
macro EmitFastNewAllArguments(implicit context: Context)(
frame: FrameWithArguments, argc: intptr): JSArray {
return arguments::NewAllArguments(frame, argc);
}
@export
macro EmitFastNewRestArguments(implicit context: Context)(_f: JSFunction):
JSArray {
const info = GetFrameWithArgumentsInfo();
return arguments::NewRestArguments(info);
}
@export
macro EmitFastNewStrictArguments(implicit context: Context)(_f: JSFunction):
JSStrictArgumentsObject {
const info = GetFrameWithArgumentsInfo();
return arguments::NewStrictArguments(info);
}
@export
macro EmitFastNewSloppyArguments(implicit context: Context)(f: JSFunction):
JSSloppyArgumentsObject {
const info = GetFrameWithArgumentsInfo();
return arguments::NewSloppyArguments(info, f);
}