Commit 887f8760 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Model arguments object materialization in graph.

This models the materialization of arguments objects in the prologue
within the IR graph. It will in turn allow us to optimize access to
these objects and also correctly handle them with inlining.

R=bmeurer@chromium.org,mvstanton@chromium.org
TEST=cctest/test-run-jsobjects/Arguments*

Review URL: https://codereview.chromium.org/1344553003

Cr-Commit-Position: refs/heads/master@{#30735}
parent 81121b40
......@@ -3152,7 +3152,11 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
// 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.
......
......@@ -115,6 +115,7 @@ REPLACE_COMPARE_IC_CALL_WITH_LANGUAGE_MODE(JSGreaterThanOrEqual, Token::GTE)
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)
......
......@@ -391,6 +391,28 @@ const StorePropertyParameters& StorePropertyParametersOf(const Operator* op) {
}
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() &&
......@@ -705,6 +727,18 @@ const Operator* JSOperatorBuilder::LoadDynamicContext(
}
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);
......
......@@ -407,6 +407,32 @@ std::ostream& operator<<(std::ostream&, StorePropertyParameters const&);
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 {
......@@ -469,6 +495,8 @@ class JSOperatorBuilder final : public ZoneObject {
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);
......
......@@ -109,6 +109,7 @@
#define JS_OBJECT_OP_LIST(V) \
V(JSCreate) \
V(JSCreateArguments) \
V(JSCreateClosure) \
V(JSCreateLiteralArray) \
V(JSCreateLiteralObject) \
......
......@@ -1179,6 +1179,11 @@ Bounds Typer::Visitor::TypeJSCreate(Node* node) {
}
Bounds Typer::Visitor::TypeJSCreateArguments(Node* node) {
return Bounds(Type::None(), Type::OtherObject());
}
Bounds Typer::Visitor::TypeJSCreateClosure(Node* node) {
return Bounds(Type::None(), Type::OtherObject());
}
......
......@@ -511,6 +511,10 @@ void Verifier::Visitor::Check(Node* node) {
// 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());
......
......@@ -75,6 +75,7 @@
'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',
......
// 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());
}
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