// Allocate and initialize a new arguments object.
Node* callee = GetFunctionClosure();
- const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1);
+ CreateArgumentsParameters::Type type =
+ is_strict(language_mode()) || !info()->has_simple_parameters()
+ ? CreateArgumentsParameters::kUnmappedArguments
+ : CreateArgumentsParameters::kMappedArguments;
+ const Operator* op = javascript()->CreateArguments(type, 0);
Node* object = NewNode(op, callee);
// Assign the object to the arguments variable.
ReplaceWithRuntimeCall(node, fun); \
}
REPLACE_RUNTIME_CALL(JSCreate, Runtime::kAbort)
+REPLACE_RUNTIME_CALL(JSCreateArguments, Runtime::kNewArguments)
REPLACE_RUNTIME_CALL(JSCreateFunctionContext, Runtime::kNewFunctionContext)
REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
REPLACE_RUNTIME_CALL(JSCreateBlockContext, Runtime::kPushBlockContext)
}
+bool operator==(CreateArgumentsParameters const& lhs,
+ CreateArgumentsParameters const& rhs) {
+ return lhs.type() == rhs.type() && lhs.start_index() == rhs.start_index();
+}
+
+
+bool operator!=(CreateArgumentsParameters const& lhs,
+ CreateArgumentsParameters const& rhs) {
+ return !(lhs == rhs);
+}
+
+
+size_t hash_value(CreateArgumentsParameters const& p) {
+ return base::hash_combine(p.type(), p.start_index());
+}
+
+
+std::ostream& operator<<(std::ostream& os, CreateArgumentsParameters const& p) {
+ return os << p.type() << ", " << p.start_index();
+}
+
+
bool operator==(CreateClosureParameters const& lhs,
CreateClosureParameters const& rhs) {
return lhs.pretenure() == rhs.pretenure() &&
}
+const Operator* JSOperatorBuilder::CreateArguments(
+ CreateArgumentsParameters::Type type, int start_index) {
+ DCHECK_IMPLIES(start_index, type == CreateArgumentsParameters::kRestArray);
+ CreateArgumentsParameters parameters(type, start_index);
+ return new (zone()) Operator1<CreateArgumentsParameters>( // --
+ IrOpcode::kJSCreateArguments, Operator::kNoThrow, // opcode
+ "JSCreateArguments", // name
+ 1, 1, 1, 1, 1, 0, // counts
+ parameters); // parameter
+}
+
+
const Operator* JSOperatorBuilder::CreateClosure(
Handle<SharedFunctionInfo> shared_info, PretenureFlag pretenure) {
CreateClosureParameters parameters(shared_info, pretenure);
const StorePropertyParameters& StorePropertyParametersOf(const Operator* op);
+// Defines specifics about arguments object or rest parameter creation. This is
+// used as a parameter by JSCreateArguments operators.
+class CreateArgumentsParameters final {
+ public:
+ enum Type { kMappedArguments, kUnmappedArguments, kRestArray };
+ CreateArgumentsParameters(Type type, int start_index)
+ : type_(type), start_index_(start_index) {}
+
+ Type type() const { return type_; }
+ int start_index() const { return start_index_; }
+
+ private:
+ const Type type_;
+ const int start_index_;
+};
+
+bool operator==(CreateArgumentsParameters const&,
+ CreateArgumentsParameters const&);
+bool operator!=(CreateArgumentsParameters const&,
+ CreateArgumentsParameters const&);
+
+size_t hash_value(CreateArgumentsParameters const&);
+
+std::ostream& operator<<(std::ostream&, CreateArgumentsParameters const&);
+
+
// Defines shared information for the closure that should be created. This is
// used as a parameter by JSCreateClosure operators.
class CreateClosureParameters final {
const Operator* Yield();
const Operator* Create();
+ const Operator* CreateArguments(CreateArgumentsParameters::Type type,
+ int start_index);
const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info,
PretenureFlag pretenure);
const Operator* CreateLiteralArray(int literal_flags);
#define JS_OBJECT_OP_LIST(V) \
V(JSCreate) \
+ V(JSCreateArguments) \
V(JSCreateClosure) \
V(JSCreateLiteralArray) \
V(JSCreateLiteralObject) \
}
+Bounds Typer::Visitor::TypeJSCreateArguments(Node* node) {
+ return Bounds(Type::None(), Type::OtherObject());
+}
+
+
Bounds Typer::Visitor::TypeJSCreateClosure(Node* node) {
return Bounds(Type::None(), Type::OtherObject());
}
// Type is Object.
CheckUpperIs(node, Type::Object());
break;
+ case IrOpcode::kJSCreateArguments:
+ // Type is OtherObject.
+ CheckUpperIs(node, Type::OtherObject());
+ break;
case IrOpcode::kJSCreateClosure:
// Type is Function.
CheckUpperIs(node, Type::OtherObject());
'compiler/test-run-jsbranches.cc',
'compiler/test-run-jscalls.cc',
'compiler/test-run-jsexceptions.cc',
+ 'compiler/test-run-jsobjects.cc',
'compiler/test-run-jsops.cc',
'compiler/test-run-machops.cc',
'compiler/test-run-native-calls.cc',
--- /dev/null
+// Copyright 2015 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.
+
+#include "test/cctest/compiler/function-tester.h"
+
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+TEST(ArgumentsMapped) {
+ FunctionTester T("(function(a) { return arguments; })");
+
+ Handle<Object> arguments;
+ T.Call(T.Val(19), T.Val(23), T.Val(42), T.Val(65)).ToHandle(&arguments);
+ CHECK(arguments->IsJSObject() && !arguments->IsJSArray());
+ CHECK(JSObject::cast(*arguments)->HasSloppyArgumentsElements());
+ Handle<String> l = T.isolate->factory()->length_string();
+ Handle<Object> length = JSObject::GetProperty(arguments, l).ToHandleChecked();
+ CHECK_EQ(4, length->Number());
+}
+
+
+TEST(ArgumentsUnmapped) {
+ FunctionTester T("(function(a) { 'use strict'; return arguments; })");
+
+ Handle<Object> arguments;
+ T.Call(T.Val(19), T.Val(23), T.Val(42), T.Val(65)).ToHandle(&arguments);
+ CHECK(arguments->IsJSObject() && !arguments->IsJSArray());
+ CHECK(!JSObject::cast(*arguments)->HasSloppyArgumentsElements());
+ Handle<String> l = T.isolate->factory()->length_string();
+ Handle<Object> length = JSObject::GetProperty(arguments, l).ToHandleChecked();
+ CHECK_EQ(4, length->Number());
+}
+
+
+TEST(ArgumentsRest) {
+ FLAG_harmony_rest_parameters = true;
+ FunctionTester T("(function(a, ...args) { return args; })");
+
+ Handle<Object> arguments;
+ T.Call(T.Val(19), T.Val(23), T.Val(42), T.Val(65)).ToHandle(&arguments);
+ CHECK(arguments->IsJSObject() && arguments->IsJSArray());
+ CHECK(!JSObject::cast(*arguments)->HasSloppyArgumentsElements());
+ Handle<String> l = T.isolate->factory()->length_string();
+ Handle<Object> length = JSObject::GetProperty(arguments, l).ToHandleChecked();
+ CHECK_EQ(3, length->Number());
+}