v8/test/unittests/compiler/js-create-lowering-unittest.cc
Victor Gomes c48096d442 Reland "[runtime] Remove extension slots from context objects"
This is a reland of c07c02e1c4

Original change's description:
> [runtime] Remove extension slots from context objects
>
> Context objects have an extension slot, which contains further
> additional data that depends on the type of the context.
>
> This CL removes the extension slot from contexts that don't need
> them, hence reducing memory.
>
> The following contexts will still have an extension slot: native,
> module, await, block and with contexts. See objects/contexts.h for
> what the slot is used for.
> The following contexts will not have an extension slot anymore (they
> were not used before): script, catch and builtin contexts.
> Eval and function contexts only have the extension slot if they
> contain a sloppy eval.
>
> Bug: v8:9744
> Change-Id: I8ca56c22fa02437bbac392ea72174ebfca80e030
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1863191
> Commit-Queue: Victor Gomes <victorgomes@google.com>
> Reviewed-by: Toon Verwaest <verwaest@chromium.org>
> Reviewed-by: Jakob Gruber <jgruber@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Leszek Swirski <leszeks@chromium.org>
> Reviewed-by: Peter Marshall <petermarshall@chromium.org>
> Auto-Submit: Victor Gomes <victorgomes@google.com>
> Cr-Commit-Position: refs/heads/master@{#64372}

TBR=verwaest@chromium.org,jgruber@chromium.org,ulan@chromium.org,leszeks@chromium.org,petermarshall@chromium.org

Bug: v8:9744
Change-Id: I0749cc2d8f59940c25841736634a70047116d647
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1869192
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Auto-Submit: Victor Gomes <victorgomes@google.com>
Cr-Commit-Position: refs/heads/master@{#64380}
2019-10-18 13:04:55 +00:00

217 lines
8.4 KiB
C++

// Copyright 2016 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 "src/compiler/js-create-lowering.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"
#include "src/execution/isolate-inl.h"
#include "src/objects/arguments.h"
#include "src/objects/feedback-vector.h"
#include "test/unittests/compiler/compiler-test-utils.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
#include "testing/gmock-support.h"
using testing::_;
using testing::BitEq;
using testing::IsNaN;
namespace v8 {
namespace internal {
namespace compiler {
class JSCreateLoweringTest : public TypedGraphTest {
public:
JSCreateLoweringTest()
: TypedGraphTest(3),
javascript_(zone()),
deps_(broker(), zone()),
handle_scope_(isolate()) {}
~JSCreateLoweringTest() override = default;
protected:
Reduction Reduce(Node* node) {
MachineOperatorBuilder machine(zone());
SimplifiedOperatorBuilder simplified(zone());
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph(), tick_counter());
JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph, broker(),
zone());
return reducer.Reduce(node);
}
Node* FrameState(Handle<SharedFunctionInfo> shared, Node* outer_frame_state) {
Node* state_values =
graph()->NewNode(common()->StateValues(0, SparseInputMask::Dense()));
return graph()->NewNode(
common()->FrameState(
BailoutId::None(), OutputFrameStateCombine::Ignore(),
common()->CreateFrameStateFunctionInfo(
FrameStateType::kInterpretedFunction, 1, 0, shared)),
state_values, state_values, state_values, NumberConstant(0),
UndefinedConstant(), outer_frame_state);
}
JSOperatorBuilder* javascript() { return &javascript_; }
private:
JSOperatorBuilder javascript_;
CompilationDependencies deps_;
CanonicalHandleScope handle_scope_;
};
// -----------------------------------------------------------------------------
// JSCreate
TEST_F(JSCreateLoweringTest, JSCreate) {
Handle<JSFunction> function = isolate()->object_function();
Node* const target = graph()->NewNode(common()->HeapConstant(function));
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r =
Reduce(graph()->NewNode(javascript()->Create(), target, target, context,
EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsFinishRegion(
IsAllocate(IsNumberConstant(function->initial_map().instance_size()),
IsBeginRegion(effect), control),
_));
}
// -----------------------------------------------------------------------------
// JSCreateArguments
TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedMapped) {
Node* const closure = Parameter(Type::Any());
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->regexp_function()->shared(),
isolate());
Node* const frame_state_outer = FrameState(shared, graph()->start());
Node* const frame_state_inner = FrameState(shared, frame_state_outer);
Reduction r = Reduce(graph()->NewNode(
javascript()->CreateArguments(CreateArgumentsType::kMappedArguments),
closure, context, frame_state_inner, effect));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsFinishRegion(
IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize), _, _),
_));
}
TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedUnmapped) {
Node* const closure = Parameter(Type::Any());
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->regexp_function()->shared(),
isolate());
Node* const frame_state_outer = FrameState(shared, graph()->start());
Node* const frame_state_inner = FrameState(shared, frame_state_outer);
Reduction r = Reduce(graph()->NewNode(
javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
closure, context, frame_state_inner, effect));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsFinishRegion(
IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize), _, _),
_));
}
TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) {
Node* const closure = Parameter(Type::Any());
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->regexp_function()->shared(),
isolate());
Node* const frame_state_outer = FrameState(shared, graph()->start());
Node* const frame_state_inner = FrameState(shared, frame_state_outer);
Reduction r = Reduce(graph()->NewNode(
javascript()->CreateArguments(CreateArgumentsType::kRestParameter),
closure, context, frame_state_inner, effect));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(JSArray::kSize), _, _), _));
}
// -----------------------------------------------------------------------------
// JSCreateFunctionContext
TEST_F(JSCreateLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction const r = Reduce(graph()->NewNode(
javascript()->CreateFunctionContext(
handle(ScopeInfo::Empty(isolate()), isolate()), 8, FUNCTION_SCOPE),
context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
8 + Context::MIN_CONTEXT_SLOTS)),
IsBeginRegion(_), control),
_));
}
// -----------------------------------------------------------------------------
// JSCreateWithContext
TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
Handle<ScopeInfo> scope_info =
ReadOnlyRoots(isolate()).empty_function_scope_info_handle();
Node* const object = Parameter(Type::Receiver());
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r =
Reduce(graph()->NewNode(javascript()->CreateWithContext(scope_info),
object, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
Context::MIN_CONTEXT_EXTENDED_SLOTS)),
IsBeginRegion(_), control),
_));
}
// -----------------------------------------------------------------------------
// JSCreateCatchContext
TEST_F(JSCreateLoweringTest, JSCreateCatchContext) {
Handle<ScopeInfo> scope_info =
ReadOnlyRoots(isolate()).empty_function_scope_info_handle();
Node* const exception = Parameter(Type::Receiver());
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r =
Reduce(graph()->NewNode(javascript()->CreateCatchContext(scope_info),
exception, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
Context::MIN_CONTEXT_SLOTS + 1)),
IsBeginRegion(_), control),
_));
}
} // namespace compiler
} // namespace internal
} // namespace v8