Commit bc0c25b4 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque] Implement Rest/Strict/Sloppy argument stubs in Torque

Bug: v8:7793
Change-Id: Ib950ce398f101779a4654353d08ce947b8e05a66
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1526016Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Daniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65518}
parent 1b450a17
......@@ -1486,8 +1486,6 @@ v8_source_set("v8_initializers") {
sources = [
### gcmole(all) ###
"src/builtins/builtins-arguments-gen.cc",
"src/builtins/builtins-arguments-gen.h",
"src/builtins/builtins-array-gen.cc",
"src/builtins/builtins-array-gen.h",
"src/builtins/builtins-async-function-gen.cc",
......
......@@ -140,6 +140,10 @@ type NoSharedNameSentinel extends Smi;
extern class ScopeInfo extends FixedArray;
operator '[]' macro LoadScopeInfoElement(s: ScopeInfo, i: intptr): Object {
return s.objects[i];
}
// Specialized types. The following three type definitions don't correspond to
// actual C++ classes, but have Is... methods that check additional constraints.
......@@ -331,6 +335,9 @@ extern enum PrimitiveType { kString, kBoolean, kSymbol, kNumber }
const kNameDictionaryInitialCapacity:
constexpr int32 generates 'NameDictionary::kInitialCapacity';
const kScopeInfoFlagsIndex:
constexpr int32 generates 'ScopeInfo::Fields::kFlags';
type TheHole extends Oddball;
type Null extends Oddball;
type Undefined extends Oddball;
......@@ -865,6 +872,7 @@ extern macro EmptyFixedArrayConstant(): EmptyFixedArray;
extern macro PromiseCapabilityMapConstant(): Map;
extern macro OneByteStringMapConstant(): Map;
extern macro StringMapConstant(): Map;
extern macro SloppyArgumentsElementsMapConstant(): Map;
const kFixedArrayMap: Map = FixedArrayMapConstant();
const kCOWMap: Map = FixedCOWArrayMapConstant();
......@@ -875,6 +883,7 @@ const kPromiseCapabilityMap: Map = PromiseCapabilityMapConstant();
const kOneByteStringMap: Map = OneByteStringMapConstant();
// The map of a non-internalized internal SeqTwoByteString.
const kStringMap: Map = StringMapConstant();
const kSloppyArgumentsElementsMap: Map = SloppyArgumentsElementsMapConstant();
extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map):
bool;
......@@ -985,6 +994,18 @@ macro GetRegExpLastMatchInfo(implicit context: Context)(): RegExpMatchInfo {
return %RawDownCast<RegExpMatchInfo>(LoadNativeContext(
context)[NativeContextSlot::REGEXP_LAST_MATCH_INFO_INDEX]);
}
macro GetStrictArgumentsMap(implicit context: Context)(): Map {
return UnsafeCast<Map>(LoadNativeContext(
context)[NativeContextSlot::STRICT_ARGUMENTS_MAP_INDEX]);
}
macro GetSloppyArgumentsMap(implicit context: Context)(): Map {
return UnsafeCast<Map>(LoadNativeContext(
context)[NativeContextSlot::SLOPPY_ARGUMENTS_MAP_INDEX]);
}
macro GetFastAliasedArgumentsMap(implicit context: Context)(): Map {
return UnsafeCast<Map>(LoadNativeContext(
context)[NativeContextSlot::FAST_ALIASED_ARGUMENTS_MAP_INDEX]);
}
extern transitioning macro Call(Context, Callable, JSAny): JSAny;
extern transitioning macro Call(Context, Callable, JSAny, JSAny): JSAny;
......@@ -1508,3 +1529,5 @@ macro ReplaceTheHoleWithUndefined(o: JSAny|TheHole): JSAny {
}
}
}
extern macro DecodeScopeInfoHasContextExtension(intptr): intptr;
This diff is collapsed.
// Copyright 2017 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.
#ifndef V8_BUILTINS_BUILTINS_ARGUMENTS_GEN_H_
#define V8_BUILTINS_BUILTINS_ARGUMENTS_GEN_H_
#include "src/codegen/code-stub-assembler.h"
namespace v8 {
namespace internal {
// TODO(v8:9396): these declarations pollute the v8::internal scope.
using CodeAssemblerState = compiler::CodeAssemblerState;
using CodeAssemblerLabel = compiler::CodeAssemblerLabel;
class ArgumentsBuiltinsAssembler : public CodeStubAssembler {
public:
explicit ArgumentsBuiltinsAssembler(CodeAssemblerState* state)
: CodeStubAssembler(state) {}
TNode<JSObject> EmitFastNewStrictArguments(TNode<Context> context,
TNode<JSFunction> function);
TNode<JSObject> EmitFastNewSloppyArguments(TNode<Context> context,
TNode<JSFunction> function);
TNode<JSObject> EmitFastNewRestParameter(TNode<Context> context,
TNode<JSFunction> function);
private:
struct ArgumentsAllocationResult {
TNode<JSObject> arguments_object;
TNode<FixedArray> elements;
TNode<FixedArray> parameter_map;
};
// Allocates an an arguments (either rest, strict or sloppy) together with the
// FixedArray elements for the arguments and a parameter map (for sloppy
// arguments only, or empty TNode<> otherwise).
ArgumentsAllocationResult AllocateArgumentsObject(
TNode<Map> map, TNode<BInt> arguments, TNode<BInt> mapped_arguments,
int base_size);
// For Rest parameters and Strict arguments, the copying of parameters from
// the stack into the arguments object is straight-forward and shares much of
// the same underlying logic, which is encapsulated by this function. It
// allocates an arguments-like object of size |base_size| with the map |map|,
// and then copies |rest_count| arguments from the stack frame pointed to by
// |frame_ptr| starting from |first_arg|. |arg_count| == |first_arg| +
// |rest_count|.
TNode<JSObject> ConstructParametersObjectFromArgs(
TNode<Map> map, TNode<RawPtrT> frame_ptr, TNode<BInt> arg_count,
TNode<BInt> first_arg, TNode<BInt> rest_count, int base_size);
};
} // namespace internal
} // namespace v8
#endif // V8_BUILTINS_BUILTINS_ARGUMENTS_GEN_H_
......@@ -11,6 +11,8 @@
#include "src/objects/js-proxy.h"
#include "src/objects/objects-inl.h"
#include "torque-generated/exported-macros-assembler-tq.h"
namespace v8 {
namespace internal {
......@@ -58,64 +60,6 @@ TNode<JSProxy> ProxiesCodeStubAssembler::AllocateProxy(
return CAST(proxy);
}
TNode<JSArray> ProxiesCodeStubAssembler::AllocateJSArrayForCodeStubArguments(
TNode<Context> context, const CodeStubArguments& args,
TNode<IntPtrT> argc) {
Comment("AllocateJSArrayForCodeStubArguments");
CSA_ASSERT(this, IsValidPositiveSmi(argc));
Label if_empty_array(this), allocate_js_array(this);
// Do not use AllocateJSArray since {elements} might end up in LOS.
TVARIABLE(FixedArrayBase, elements);
GotoIf(WordEqual(argc, IntPtrConstant(0)), &if_empty_array);
{
Label if_large_object(this, Label::kDeferred);
TNode<FixedArrayBase> allocated_elements = AllocateFixedArray(
PACKED_ELEMENTS, argc, INTPTR_PARAMETERS, kAllowLargeObjectAllocation);
elements = allocated_elements;
TVARIABLE(IntPtrT, offset,
IntPtrConstant(FixedArrayBase::kHeaderSize - kHeapObjectTag));
VariableList list({&offset}, zone());
GotoIf(
UintPtrGreaterThan(argc, IntPtrConstant(FixedArray::kMaxRegularLength)),
&if_large_object);
args.ForEach(list, [&](TNode<Object> arg) {
StoreNoWriteBarrier(MachineRepresentation::kTagged, allocated_elements,
offset.value(), arg);
Increment(&offset, kTaggedSize);
});
Goto(&allocate_js_array);
BIND(&if_large_object);
{
args.ForEach(list, [&](TNode<Object> arg) {
Store(allocated_elements, offset.value(), arg);
Increment(&offset, kTaggedSize);
});
Goto(&allocate_js_array);
}
}
BIND(&if_empty_array);
{
elements = EmptyFixedArrayConstant();
Goto(&allocate_js_array);
}
BIND(&allocate_js_array);
// Allocate the result JSArray.
TNode<NativeContext> native_context = LoadNativeContext(context);
TNode<Map> array_map =
LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
TNode<Smi> length = SmiTag(argc);
TNode<JSArray> array = AllocateJSArray(array_map, elements.value(), length);
return array;
}
TNode<Context> ProxiesCodeStubAssembler::CreateProxyRevokeFunctionContext(
TNode<JSProxy> proxy, TNode<NativeContext> native_context) {
const TNode<Context> context =
......@@ -177,7 +121,9 @@ TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) {
// 7. Let argArray be CreateArrayFromList(argumentsList).
TNode<JSArray> array =
AllocateJSArrayForCodeStubArguments(context, args, argc_ptr);
EmitFastNewAllArguments(UncheckedCast<Context>(context),
UncheckedCast<RawPtrT>(LoadFramePointer()),
UncheckedCast<IntPtrT>(argc_ptr));
// 8. Return Call(trap, handler, «target, thisArgument, argArray»).
TNode<Object> result = CallJS(CodeFactory::Call(isolate()), context, trap,
......@@ -230,7 +176,9 @@ TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) {
// 7. Let argArray be CreateArrayFromList(argumentsList).
TNode<JSArray> array =
AllocateJSArrayForCodeStubArguments(context, args, argc_ptr);
EmitFastNewAllArguments(UncheckedCast<Context>(context),
UncheckedCast<RawPtrT>(LoadFramePointer()),
UncheckedCast<IntPtrT>(argc_ptr));
// 8. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »).
TNode<Object> new_obj = CallJS(CodeFactory::Call(isolate()), context, trap,
......
......@@ -39,10 +39,6 @@ class ProxiesCodeStubAssembler : public CodeStubAssembler {
kProxyContextLength,
};
TNode<JSArray> AllocateJSArrayForCodeStubArguments(
TNode<Context> context, const CodeStubArguments& args,
TNode<IntPtrT> argc);
private:
TNode<Context> CreateProxyRevokeFunctionContext(
TNode<JSProxy> proxy, TNode<NativeContext> native_context);
......
......@@ -228,10 +228,18 @@ extern macro IntPtrToBInt(intptr): bint;
Convert<bint, intptr>(v: intptr): bint {
return IntPtrToBInt(v);
}
extern macro BIntToIntPtr(bint): intptr;
Convert<intptr, bint>(v: bint): intptr {
return BIntToIntPtr(v);
}
extern macro SmiToBInt(Smi): bint;
Convert<bint, Smi>(v: Smi): bint {
return SmiToBInt(v);
}
extern macro BIntToSmi(bint): Smi;
Convert<Smi, bint>(v: bint): Smi {
return BIntToSmi(v);
}
Convert<PromiseState, int32>(s: int32): PromiseState {
return %RawDownCast<PromiseState>(s);
}
......@@ -10,52 +10,55 @@ struct Arguments {
}
extern operator '[]' macro GetArgumentValue(Arguments, intptr): JSAny;
extern macro GetFrameArguments(FrameWithArguments, intptr): Arguments;
namespace arguments {
@export
struct ArgumentsInfo {
frame: Frame;
argument_count: bint;
formal_parameter_count: bint;
struct ArgumentsIterator {
macro Next(): Object labels NoMore {
if (this.current == this.arguments.length) goto NoMore;
return this.arguments[this.current++];
}
const arguments: Arguments;
current: intptr;
}
// Calculates and returns the frame pointer, argument count and formal
// parameter count to be used to access a function's parameters, taking
// argument adapter frames into account.
//
// TODO(danno):
// This macro is should only be used in builtins that can be called from
// interpreted or JITted code, not from CSA/Torque builtins (the number of
// returned formal parameters would be wrong).
// It is difficult to actually check/assert this, since interpreted or JITted
// frames are StandardFrames, but so are hand-written builtins. Doing that
// more refined check would be prohibitively expensive.
@export
macro GetArgumentsFrameAndCount(implicit context: Context)(f: JSFunction):
ArgumentsInfo {
const frame: Frame = LoadParentFramePointer();
assert(frame.function == f);
const shared: SharedFunctionInfo = f.shared_function_info;
const formalParameterCount: bint =
Convert<bint>(Convert<int32>(shared.formal_parameter_count));
const argumentCount: bint = formalParameterCount;
const adaptor: ArgumentsAdaptorFrame =
Cast<ArgumentsAdaptorFrame>(frame.caller)
otherwise return ArgumentsInfo{
frame,
argument_count: argumentCount,
formal_parameter_count: formalParameterCount
};
return ArgumentsInfo{
frame: adaptor,
argument_count: Convert<bint>(adaptor.length),
formal_parameter_count: formalParameterCount
};
}
struct FrameWithArgumentsInfo {
const frame: FrameWithArguments;
const argument_count: bint;
const formal_parameter_count: bint;
}
// Calculates and returns the frame pointer, argument count and formal
// parameter count to be used to access a function's parameters, taking
// argument adapter frames into account.
//
// TODO(danno):
// This macro is should only be used in builtins that can be called from
// interpreted or JITted code, not from CSA/Torque builtins (the number of
// returned formal parameters would be wrong).
// It is difficult to actually check/assert this, since interpreted or JITted
// frames are StandardFrames, but so are hand-written builtins. Doing that
// more refined check would be prohibitively expensive.
macro GetFrameWithArgumentsInfo(implicit context: Context)():
FrameWithArgumentsInfo {
const frame =
Cast<StandardFrame>(LoadParentFramePointer()) otherwise unreachable;
const f: JSFunction = frame.function;
const shared: SharedFunctionInfo = f.shared_function_info;
const formalParameterCount: bint =
Convert<bint>(Convert<int32>(shared.formal_parameter_count));
const argumentCount: bint = formalParameterCount;
const adaptor = Cast<ArgumentsAdaptorFrame>(frame.caller)
otherwise return FrameWithArgumentsInfo{
frame,
argument_count: argumentCount,
formal_parameter_count: formalParameterCount
};
return FrameWithArgumentsInfo{
frame: adaptor,
argument_count: Convert<bint>(adaptor.length),
formal_parameter_count: formalParameterCount
};
}
......@@ -13435,5 +13435,10 @@ void PrototypeCheckAssembler::CheckAndBranch(TNode<HeapObject> prototype,
}
}
TNode<IntPtrT> CodeStubAssembler::DecodeScopeInfoHasContextExtension(
TNode<IntPtrT> flags) {
return Signed(DecodeWord<ScopeInfo::HasContextExtensionSlotField>(flags));
}
} // namespace internal
} // namespace v8
......@@ -2742,6 +2742,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word, uint32_t shift,
uint32_t mask);
TNode<IntPtrT> DecodeScopeInfoHasContextExtension(TNode<IntPtrT> flags);
// Returns a node that contains the updated values of a |BitField|.
template <typename BitField>
TNode<Word32T> UpdateWord32(TNode<Word32T> word, TNode<Uint32T> value) {
......
......@@ -7,7 +7,6 @@
#include <array>
#include <tuple>
#include "src/builtins/builtins-arguments-gen.h"
#include "src/builtins/builtins-constructor-gen.h"
#include "src/builtins/builtins-iterator-gen.h"
#include "src/codegen/code-factory.h"
......@@ -26,6 +25,7 @@
#include "src/objects/shared-function-info.h"
#include "src/objects/source-text-module.h"
#include "src/utils/ostreams.h"
#include "torque-generated/exported-macros-assembler-tq.h"
namespace v8 {
namespace internal {
......@@ -33,6 +33,7 @@ namespace interpreter {
namespace {
using compiler::CodeAssemblerState;
using compiler::Node;
using Label = CodeStubAssembler::Label;
......@@ -2830,9 +2831,7 @@ IGNITION_HANDLER(CreateMappedArguments, InterpreterAssembler) {
BIND(&if_not_duplicate_parameters);
{
ArgumentsBuiltinsAssembler constructor_assembler(state());
TNode<JSObject> result =
constructor_assembler.EmitFastNewSloppyArguments(context, closure);
TNode<JSObject> result = EmitFastNewSloppyArguments(context, closure);
SetAccumulator(result);
Dispatch();
}
......@@ -2852,7 +2851,7 @@ IGNITION_HANDLER(CreateMappedArguments, InterpreterAssembler) {
IGNITION_HANDLER(CreateUnmappedArguments, InterpreterAssembler) {
TNode<Context> context = GetContext();
TNode<JSFunction> closure = CAST(LoadRegister(Register::function_closure()));
ArgumentsBuiltinsAssembler builtins_assembler(state());
TorqueGeneratedExportedMacrosAssembler builtins_assembler(state());
TNode<JSObject> result =
builtins_assembler.EmitFastNewStrictArguments(context, closure);
SetAccumulator(result);
......@@ -2865,9 +2864,9 @@ IGNITION_HANDLER(CreateUnmappedArguments, InterpreterAssembler) {
IGNITION_HANDLER(CreateRestParameter, InterpreterAssembler) {
TNode<JSFunction> closure = CAST(LoadRegister(Register::function_closure()));
TNode<Context> context = GetContext();
ArgumentsBuiltinsAssembler builtins_assembler(state());
TorqueGeneratedExportedMacrosAssembler builtins_assembler(state());
TNode<JSObject> result =
builtins_assembler.EmitFastNewRestParameter(context, closure);
builtins_assembler.EmitFastNewRestArguments(context, closure);
SetAccumulator(result);
Dispatch();
}
......
......@@ -32,3 +32,200 @@ type SloppyArgumentsElements extends FixedArray;
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 scopeInfoFlags = Convert<intptr>(
UnsafeCast<Smi>(context.scope_info[kScopeInfoFlagsIndex]));
const contextExtentionSize =
DecodeScopeInfoHasContextExtension(scopeInfoFlags);
const contextHeaderSize = MIN_CONTEXT_SLOTS + contextExtentionSize;
// 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);
}
......@@ -20,6 +20,9 @@ extern class NativeContext extends Context;
extern class ScriptContext extends Context generates 'TNode<Context>';
extern class WithContext extends Context generates 'TNode<Context>';
const MIN_CONTEXT_SLOTS: constexpr int31
generates 'Context::MIN_CONTEXT_SLOTS';
extern enum NativeContextSlot extends intptr constexpr 'Context::Field' {
ARRAY_BUFFER_FUN_INDEX,
ARRAY_BUFFER_NOINIT_FUN_INDEX,
......@@ -37,6 +40,9 @@ extern enum NativeContextSlot extends intptr constexpr 'Context::Field' {
REGEXP_LAST_MATCH_INFO_INDEX,
INITIAL_STRING_ITERATOR_MAP_INDEX,
SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP,
STRICT_ARGUMENTS_MAP_INDEX,
SLOPPY_ARGUMENTS_MAP_INDEX,
FAST_ALIASED_ARGUMENTS_MAP_INDEX,
PROMISE_FUNCTION_INDEX,
PROMISE_THEN_INDEX,
......
......@@ -115,3 +115,9 @@ extern macro ExtractFixedArray(
extern macro ExtractFixedArray(
FixedArray, intptr, intptr, intptr,
constexpr ExtractFixedArrayFlag): FixedArray;
macro NewFixedArray<I: type>(length: intptr, it: I): FixedArray {
if (length == 0) return kEmptyFixedArray;
return new
FixedArray{map: kFixedArrayMap, length: Convert<Smi>(length), objects: ...it};
}
......@@ -39,7 +39,7 @@ void CheckAlreadyDeclared(const std::string& name, const char* new_type) {
FilterDeclarables<T>(Declarations::TryLookupShallow(QualifiedName(name)));
if (!declarations.empty()) {
Scope* scope = CurrentScope::Get();
ReportError("cannot redeclare ", name, " (type ", new_type, scope, ")");
ReportError("cannot redeclare ", name, " (type ", *new_type, scope, ")");
}
}
......
......@@ -720,6 +720,22 @@ TEST(TestBitFieldUintptrOps) {
ft.Call(ft.Val(val2), ft.Val(val3));
}
TEST(TestTestParentFrameArguments) {
CcTest::InitializeVM();
Isolate* isolate(CcTest::i_isolate());
i::HandleScope scope(isolate);
Handle<Context> context =
Utils::OpenHandle(*v8::Isolate::GetCurrent()->GetCurrentContext());
CodeAssemblerTester asm_tester(isolate, 1);
TestTorqueAssembler m(asm_tester.state());
{
m.TestParentFrameArguments(
m.UncheckedCast<Context>(m.HeapConstant(context)));
m.Return(m.UndefinedConstant());
}
asm_tester.GenerateCode();
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -811,6 +811,14 @@ namespace test {
check(x.TestMethod2() == Null);
}
@export
macro TestParentFrameArguments(implicit context: Context)() {
const parentFrame = LoadParentFramePointer();
const castFrame = Cast<StandardFrame>(parentFrame) otherwise unreachable;
const arguments = GetFrameArguments(castFrame, 1);
ArgumentsIterator{arguments, current: 0};
}
struct TestIterator {
macro Next(): Object labels NoMore {
if (this.count-- == 0) goto NoMore;
......
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