[nci] Implement missing generic lowering bits

... for nci code, in which several phases of the compiler are not
active:

LowerJSCreateCatchContext
LowerJSCreateEmptyLiteralObject
LowerJSCreateIterResultObject
LowerJSCreateWithContext
LowerJSGetIterator
LowerJSGetTemplateObject

With this change, the nci variant passes the test suite. Tests
relying on turbofan-specific behavior (e.g. deopts) are skipped.

Bug: v8:8888
Change-Id: I709178241e9b25e7480a39b4fb64bdcf576483be
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2245604
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68381}
This commit is contained in:
Jakob Gruber 2020-06-16 14:18:55 +02:00 committed by Commit Bot
parent e1970c9738
commit d8cd725f7b
10 changed files with 252 additions and 50 deletions

View File

@ -1083,6 +1083,7 @@ torque_files = [
"src/builtins/ic-callable.tq",
"src/builtins/ic.tq",
"src/builtins/internal-coverage.tq",
"src/builtins/internal.tq",
"src/builtins/iterator.tq",
"src/builtins/math.tq",
"src/builtins/number.tq",

View File

@ -765,6 +765,11 @@ TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) {
args.PopAndReturn(var_result.value());
}
TF_BUILTIN(CreateEmptyLiteralObject, ConstructorBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Return(EmitCreateEmptyObjectLiteral(context));
}
// ES #sec-number-constructor
TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));

View File

@ -96,6 +96,7 @@ namespace internal {
TFS(FastNewClosure, kSharedFunctionInfo, kFeedbackCell) \
TFC(FastNewFunctionContextEval, FastNewFunctionContext) \
TFC(FastNewFunctionContextFunction, FastNewFunctionContext) \
TFS(CreateEmptyLiteralObject) \
TFS(CreateRegExpLiteral, kFeedbackVector, kSlot, kPattern, kFlags) \
TFS(CreateEmptyArrayLiteral, kFeedbackVector, kSlot) \
TFS(CreateShallowArrayLiteral, kFeedbackVector, kSlot, kConstantElements) \

35
src/builtins/internal.tq Normal file
View File

@ -0,0 +1,35 @@
// Copyright 2020 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.
namespace internal {
namespace runtime {
extern runtime GetTemplateObject(implicit context: Context)(
TemplateObjectDescription, SharedFunctionInfo, Smi): JSAny;
}
builtin GetTemplateObject(
context: Context, shared: SharedFunctionInfo,
description: TemplateObjectDescription, slot: uintptr,
maybeFeedbackVector: FeedbackVector|Undefined): JSArray {
// TODO(jgruber): Consider merging with the GetTemplateObject bytecode
// handler; the current advantage of the split implementation is that the
// bytecode can skip most work if feedback exists.
try {
const vector =
Cast<FeedbackVector>(maybeFeedbackVector) otherwise CallRuntime;
return Cast<JSArray>(ic::LoadFeedbackVectorSlot(vector, slot))
otherwise CallRuntime;
} label CallRuntime deferred {
const result = UnsafeCast<JSArray>(runtime::GetTemplateObject(
description, shared, Convert<Smi>(Signed(slot))));
const vector =
Cast<FeedbackVector>(maybeFeedbackVector) otherwise return result;
ic::StoreFeedbackVectorSlot(vector, slot, result);
return result;
}
}
} // namespace internal

View File

@ -6093,6 +6093,10 @@ Reduction JSCallReducer::ReduceStringFromCodePoint(Node* node) {
}
Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) {
// TODO(jgruber): We could reduce here when generating native context
// independent code, if LowerJSCreateStringIterator were implemented in
// generic lowering.
if (broker()->is_native_context_independent()) return NoChange();
CallParameters const& p = CallParametersOf(node->op());
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange();
@ -6218,6 +6222,11 @@ Reduction JSCallReducer::ReduceStringPrototypeConcat(Node* node) {
}
Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
// TODO(jgruber): We could reduce here when generating native context
// independent code, if LowerJSCreatePromise were implemented in generic
// lowering.
if (broker()->is_native_context_independent()) return NoChange();
DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
PromiseBuiltinReducerAssembler a(jsgraph(), temp_zone(), node, broker());

View File

@ -18,6 +18,7 @@
#include "src/objects/feedback-cell.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/scope-info.h"
#include "src/objects/template-objects-inl.h"
namespace v8 {
namespace internal {
@ -336,13 +337,28 @@ void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
void JSGenericLowering::LowerJSGetIterator(Node* node) {
// TODO(v8:9625): Currently, the GetIterator operator is desugared in the
// native context specialization phase. Thus, the following generic lowering
// would never be reachable. We can add a check in native context
// specialization to avoid desugaring the GetIterator operator when in the
// case of megamorphic feedback and here, add a call to the
// 'GetIteratorWithFeedback' builtin. This would reduce the size of the
// compiled code as it would insert 1 call to the builtin instead of 2 calls
// resulting from the generic lowering of the LoadNamed and Call operators.
UNREACHABLE();
// is not reachable unless that phase is disabled (e.g. for
// native-context-independent code).
// We can add a check in native context specialization to avoid desugaring
// the GetIterator operator when feedback is megamorphic. This would reduce
// the size of the compiled code as it would insert 1 call to the builtin
// instead of 2 calls resulting from the generic lowering of the LoadNamed
// and Call operators.
GetIteratorParameters const& p = GetIteratorParametersOf(node->op());
Node* load_slot =
jsgraph()->TaggedIndexConstant(p.loadFeedback().slot.ToInt());
Node* call_slot =
jsgraph()->TaggedIndexConstant(p.callFeedback().slot.ToInt());
Node* feedback = jsgraph()->HeapConstant(p.callFeedback().vector);
node->InsertInput(zone(), 1, load_slot);
node->InsertInput(zone(), 2, call_slot);
node->InsertInput(zone(), 3, feedback);
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kGetIteratorWithFeedback);
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSStoreProperty(Node* node) {
@ -627,7 +643,10 @@ void JSGenericLowering::LowerJSCreateGeneratorObject(Node* node) {
}
void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kCreateIterResultObject);
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSCreateStringIterator(Node* node) {
@ -671,7 +690,21 @@ void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
}
void JSGenericLowering::LowerJSGetTemplateObject(Node* node) {
UNREACHABLE(); // Eliminated in native context specialization.
GetTemplateObjectParameters const& p =
GetTemplateObjectParametersOf(node->op());
SharedFunctionInfoRef shared(broker(), p.shared());
TemplateObjectDescriptionRef description(broker(), p.description());
node->InsertInput(zone(), 0, jsgraph()->Constant(shared));
node->InsertInput(zone(), 1, jsgraph()->Constant(description));
node->InsertInput(zone(), 2,
jsgraph()->UintPtrConstant(p.feedback().index()));
node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector));
node->RemoveInput(6); // control
ReplaceWithStubCall(
node, Builtins::CallableFor(isolate(), Builtins::kGetTemplateObject),
FrameStateFlagForCall(node));
}
void JSGenericLowering::LowerJSCreateEmptyLiteralArray(Node* node) {
@ -728,7 +761,11 @@ void JSGenericLowering::LowerJSCloneObject(Node* node) {
}
void JSGenericLowering::LowerJSCreateEmptyLiteralObject(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kCreateEmptyLiteralObject);
node->RemoveInput(0); // The closure.
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
@ -746,11 +783,15 @@ void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
}
void JSGenericLowering::LowerJSCreateWithContext(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
ReplaceWithRuntimeCall(node, Runtime::kPushWithContext);
}
void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {

View File

@ -2409,10 +2409,9 @@ IGNITION_HANDLER(CloneObject, InterpreterAssembler) {
TNode<HeapObject> maybe_feedback_vector = LoadFeedbackVector();
TNode<Context> context = GetContext();
TVARIABLE(Object, var_result);
var_result = CallBuiltin(Builtins::kCloneObjectIC, context, source, smi_flags,
slot, maybe_feedback_vector);
SetAccumulator(var_result.value());
TNode<Object> result = CallBuiltin(Builtins::kCloneObjectIC, context, source,
smi_flags, slot, maybe_feedback_vector);
SetAccumulator(result);
Dispatch();
}
@ -2422,41 +2421,18 @@ IGNITION_HANDLER(CloneObject, InterpreterAssembler) {
// accumulator, creating and caching the site object on-demand as per the
// specification.
IGNITION_HANDLER(GetTemplateObject, InterpreterAssembler) {
TNode<HeapObject> maybe_feedback_vector = LoadFeedbackVector();
TNode<Context> context = GetContext();
TNode<JSFunction> closure = CAST(LoadRegister(Register::function_closure()));
TNode<SharedFunctionInfo> shared_info = LoadObjectField<SharedFunctionInfo>(
closure, JSFunction::kSharedFunctionInfoOffset);
TNode<Object> description = LoadConstantPoolEntryAtOperandIndex(0);
TNode<UintPtrT> slot = BytecodeOperandIdx(1);
Label call_runtime(this, Label::kDeferred);
GotoIf(IsUndefined(maybe_feedback_vector), &call_runtime);
TNode<Object> cached_value =
CAST(LoadFeedbackVectorSlot(CAST(maybe_feedback_vector), slot));
GotoIf(TaggedEqual(cached_value, SmiConstant(0)), &call_runtime);
SetAccumulator(cached_value);
TNode<HeapObject> maybe_feedback_vector = LoadFeedbackVector();
TNode<Object> result =
CallBuiltin(Builtins::kGetTemplateObject, context, shared_info,
description, slot, maybe_feedback_vector);
SetAccumulator(result);
Dispatch();
BIND(&call_runtime);
{
TNode<Object> description = LoadConstantPoolEntryAtOperandIndex(0);
TNode<Smi> slot_smi = SmiTag(Signed(slot));
TNode<JSFunction> closure =
CAST(LoadRegister(Register::function_closure()));
TNode<SharedFunctionInfo> shared_info = LoadObjectField<SharedFunctionInfo>(
closure, JSFunction::kSharedFunctionInfoOffset);
TNode<Context> context = GetContext();
TNode<Object> result = CallRuntime(Runtime::kGetTemplateObject, context,
description, shared_info, slot_smi);
Label end(this);
GotoIf(IsUndefined(maybe_feedback_vector), &end);
StoreFeedbackVectorSlot(CAST(maybe_feedback_vector), slot, result);
Goto(&end);
Bind(&end);
SetAccumulator(result);
Dispatch();
}
}
// CreateClosure <index> <slot> <flags>

View File

@ -637,4 +637,14 @@
'*': [SKIP], # only relevant for mjsunit tests.
}],
################################################################################
['variant == nci', {
# Optimizes and deopts differently than TurboFan.
'test-cpu-profiler/Deopt*': [SKIP],
'test-cpu-profiler/DetailedSourcePositionAPI_Inlining': [SKIP],
'test-heap/EnsureAllocationSiteDependentCodesProcessed': [SKIP],
'test-heap/OptimizedPretenuring*': [SKIP],
'test-heap-profiler/SamplingHeapProfilerPretenuredInlineAllocations': [SKIP],
}], # variant == nci
]

View File

@ -136,7 +136,7 @@
}], # lite_mode or variant == jitless
##############################################################################
['variant == turboprop', {
['variant == turboprop or variant == nci', {
# Deopts differently than TurboFan.
'debug/debug-optimize': [SKIP],
}], # variant == turboprop

View File

@ -1273,4 +1273,128 @@
'regress/wasm/regress-9017': [SKIP],
}], # variant == slow_path
################################################################################
['variant == nci', {
# Deopts differently than TurboFan.
'compiler/is-being-interpreted*': [SKIP],
'compiler/number-comparison-truncations': [SKIP],
'compiler/redundancy-elimination': [SKIP],
'compiler/regress-9945-*': [SKIP],
'regress/regress-1049982-1': [SKIP],
'regress/regress-1049982-2': [SKIP],
# assertUnoptimized: assumes full turbofan pipeline.
'allocation-site-info': [SKIP],
'array-bounds-check-removal': [SKIP],
'array-constructor-feedback': [SKIP],
'array-literal-feedback': [SKIP],
'array-literal-transitions': [SKIP],
'array-push5': [SKIP],
'array-store-and-grow': [SKIP],
'check-bounds-array-index': [SKIP],
'check-bounds-string-from-char-code-at': [SKIP],
'compiler/abstract-equal-oddball': [SKIP],
'compiler/abstract-equal-receiver': [SKIP],
'compiler/abstract-equal-symbol': [SKIP],
'compiler/abstract-equal-undetectable': [SKIP],
'compiler/array-multiple-receiver-maps': [SKIP],
'compiler/bigint-add-no-deopt-loop': [SKIP],
'compiler/bound-functions-serialize': [SKIP],
'compiler/concurrent-invalidate-transition-map': [SKIP],
'compiler/concurrent-proto-change': [SKIP],
'compiler/constant-fold-cow-array': [SKIP],
'compiler/dataview-deopt': [SKIP],
'compiler/dataview-detached': [SKIP],
'compiler/dataview-get': [SKIP],
'compiler/dataview-set': [SKIP],
'compiler/deopt-inlined-from-call': [SKIP],
'compiler/field-representation-tracking': [SKIP],
'compiler/manual-concurrent-recompile': [SKIP],
'compiler/native-context-specialization-hole-check': [SKIP],
'compiler/number-divide': [SKIP],
'compiler/opt-higher-order-functions': [SKIP],
'compiler/promise-resolve-stable-maps': [SKIP],
'compiler/regress-905555-2': [SKIP],
'compiler/regress-905555': [SKIP],
'compiler/regress-9945-1': [SKIP],
'compiler/regress-9945-2': [SKIP],
'compiler/stress-deopt-count-2': [SKIP],
'compiler/strict-equal-receiver': [SKIP],
'compiler/string-from-code-point': [SKIP],
'concurrent-initial-prototype-change': [SKIP],
'const-field-tracking-2': [SKIP],
'const-field-tracking': [SKIP],
'deopt-recursive-eager-once': [SKIP],
'deopt-recursive-lazy-once': [SKIP],
'deopt-recursive-soft-once': [SKIP],
'deopt-unlinked': [SKIP],
'deopt-with-fp-regs': [SKIP],
'ensure-growing-store-learns': [SKIP],
'es6/array-iterator-turbo': [SKIP],
'es6/iterator-eager-deopt': [SKIP],
'es6/iterator-lazy-deopt': [SKIP],
'field-type-tracking': [SKIP],
'frozen-array-reduce': [SKIP],
'getters-on-elements': [SKIP],
'harmony/regexp-overriden-exec': [SKIP],
'keyed-load-hole-to-undefined': [SKIP],
'keyed-load-with-symbol-key': [SKIP],
'mjsunit_numfuzz': [SKIP],
'mjsunit': [SKIP],
'never-optimize': [SKIP],
'non-extensible-array-reduce': [SKIP],
'noopt': [SKIP],
'object-seal': [SKIP],
'optimized-array-every': [SKIP],
'optimized-array-findindex': [SKIP],
'optimized-array-find': [SKIP],
'optimized-array-some': [SKIP],
'optimized-filter': [SKIP],
'optimized-map': [SKIP],
'parallel-optimize-disabled': [SKIP],
'regress/regress-1016450': [SKIP],
'regress/regress-1034449': [SKIP],
'regress/regress-1073440': [SKIP],
'regress/regress-347914': [SKIP],
'regress/regress-3709': [SKIP],
'regress/regress-385565': [SKIP],
'regress/regress-410912': [SKIP],
'regress/regress-618608': [SKIP],
'regress/regress-9002': [SKIP],
'regress/regress-9441': [SKIP],
'regress/regress-961709-classes-opt': [SKIP],
'regress/regress-bind-deoptimize': [SKIP],
'regress/regress-crbug-500497': [SKIP],
'regress/regress-crbug-594183': [SKIP],
'regress/regress-embedded-cons-string': [SKIP],
'regress/regress-unlink-closures-on-deopt': [SKIP],
'regress/wasm/regress-02256b': [SKIP],
'regress/wasm/regress-02256': [SKIP],
'sealed-array-reduce': [SKIP],
'setters-on-elements': [SKIP],
'smi-mul-const': [SKIP],
'smi-mul': [SKIP],
'unary-minus-deopt': [SKIP],
# TurbofanStaticAssert: assumes full turbofan pipeline.
'compiler/catch-block-load': [SKIP],
'compiler/concurrent-inlining-1': [SKIP],
'compiler/concurrent-inlining-2': [SKIP],
'compiler/constant-fold-add-static': [SKIP],
'compiler/construct-bound-function': [SKIP],
'compiler/construct-object': [SKIP],
'compiler/construct-receiver': [SKIP],
'compiler/diamond-followedby-branch': [SKIP],
'compiler/inlined-call-polymorphic': [SKIP],
'compiler/js-create-arguments': [SKIP],
'compiler/js-create': [SKIP],
'compiler/load-elimination-const-field': [SKIP],
'compiler/serializer-accessors': [SKIP],
'compiler/serializer-apply': [SKIP],
'compiler/serializer-call': [SKIP],
'compiler/serializer-dead-after-jump': [SKIP],
'compiler/serializer-dead-after-return': [SKIP],
'compiler/serializer-feedback-propagation-1': [SKIP],
'compiler/serializer-feedback-propagation-2': [SKIP],
'compiler/serializer-transition-propagation': [SKIP],
}], # variant == nci
]