Commit 3cc7315e authored by neis's avatar neis Committed by Commit bot

Allow Turbofan optimization of Ignition generators, first version.

In the bytecode graphbuilder, translate the two generator-specific
bytecodes as a couple of runtime calls for now.

BUG=v8:4907
LOG=n

Review-Url: https://codereview.chromium.org/1957393004
Cr-Commit-Position: refs/heads/master@{#36134}
parent 61f5fbbb
......@@ -91,6 +91,7 @@ namespace internal {
V(kGraphBuildingFailed, "Optimized graph construction failed") \
V(kHeapNumberMapRegisterClobbered, "HeapNumberMap register clobbered") \
V(kHydrogenFilter, "Optimization disabled by filter") \
V(kIllegalBytecode, "Illegal bytecode") \
V(kImportDeclaration, "Import declaration") \
V(kIndexIsNegative, "Index is negative") \
V(kIndexIsTooLarge, "Index is too large") \
......
......@@ -735,13 +735,6 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
return MaybeHandle<Code>();
}
// Do not use Crankshaft/TurboFan on a generator function.
// TODO(neis): Eventually enable for Turbofan.
if (IsGeneratorFunction(info->shared_info()->kind())) {
info->AbortOptimization(kGenerator);
return MaybeHandle<Code>();
}
// Limit the number of times we try to optimize functions.
const int kMaxOptCount =
FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
......@@ -1250,6 +1243,12 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
Zone zone(info->isolate()->allocator());
CompilationInfo unoptimized(info->parse_info(), info->closure());
unoptimized.EnableDeoptimizationSupport();
// TODO(4280): For now we do not switch generators to baseline code because
// there might be suspended activations stored in generator objects on the
// heap. We could eventually go directly to TurboFan in this case.
if (shared->is_generator()) return false;
// TODO(4280): For now we disable switching to baseline code in the presence
// of interpreter activations of the given function. The reasons are:
// 1) The debugger assumes each function is either full-code or bytecode.
......@@ -1260,6 +1259,7 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
HasInterpreterActivations(info->isolate(), *shared)) {
return false;
}
// If the current code has reloc info for serialization, also include
// reloc info for serialization for the new code, so that deopt support
// can be added without losing IC state.
......
......@@ -1367,11 +1367,45 @@ void BytecodeGraphBuilder::VisitForInStep() {
}
void BytecodeGraphBuilder::VisitSuspendGenerator() {
UNIMPLEMENTED();
Node* state = environment()->LookupAccumulator();
Node* generator = environment()->LookupRegister(
bytecode_iterator().GetRegisterOperand(0));
for (int i = 0; i < environment()->register_count(); ++i) {
Node* value = environment()->LookupRegister(interpreter::Register(i));
NewNode(javascript()->CallRuntime(Runtime::kGeneratorStoreRegister),
generator, jsgraph()->Constant(i), value);
}
NewNode(javascript()->CallRuntime(Runtime::kGeneratorSetContext), generator);
NewNode(javascript()->CallRuntime(Runtime::kGeneratorSetContinuation),
generator, state);
}
void BytecodeGraphBuilder::VisitResumeGenerator() {
UNIMPLEMENTED();
FrameStateBeforeAndAfter states(this);
Node* generator = environment()->LookupRegister(
bytecode_iterator().GetRegisterOperand(0));
Node* state = NewNode(javascript()->CallRuntime(
Runtime::kGeneratorGetContinuation), generator);
// Bijection between registers and array indices must match that used in
// InterpreterAssembler::ExportRegisterFile.
for (int i = 0; i < environment()->register_count(); ++i) {
Node* value = NewNode(
javascript()->CallRuntime(Runtime::kGeneratorLoadRegister),
generator, jsgraph()->Constant(i));
environment()->BindRegister(interpreter::Register(i), value);
NewNode(javascript()->CallRuntime(Runtime::kGeneratorStoreRegister),
generator, jsgraph()->Constant(i), jsgraph()->StaleRegisterConstant());
}
NewNode(javascript()->CallRuntime(Runtime::kGeneratorSetContinuation),
generator, jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting));
environment()->BindAccumulator(state, &states);
}
void BytecodeGraphBuilder::VisitWide() {
......@@ -1385,8 +1419,8 @@ void BytecodeGraphBuilder::VisitExtraWide() {
}
void BytecodeGraphBuilder::VisitIllegal() {
// Never present in valid bytecode.
UNREACHABLE();
NewNode(javascript()->CallRuntime(Runtime::kAbort),
jsgraph()->Constant(kIllegalBytecode));
}
void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) {
......
......@@ -48,6 +48,11 @@ Node* JSGraph::OptimizedOutConstant() {
HeapConstant(factory()->optimized_out()));
}
Node* JSGraph::StaleRegisterConstant() {
return CACHED(kStaleRegisterConstant,
HeapConstant(factory()->stale_register()));
}
Node* JSGraph::UndefinedConstant() {
return CACHED(kUndefinedConstant, HeapConstant(factory()->undefined_value()));
}
......
......@@ -45,6 +45,7 @@ class JSGraph : public ZoneObject {
Node* EmptyFixedArrayConstant();
Node* HeapNumberMapConstant();
Node* OptimizedOutConstant();
Node* StaleRegisterConstant();
Node* UndefinedConstant();
Node* TheHoleConstant();
Node* TrueConstant();
......@@ -148,6 +149,7 @@ class JSGraph : public ZoneObject {
kEmptyFixedArrayConstant,
kHeapNumberMapConstant,
kOptimizedOutConstant,
kStaleRegisterConstant,
kUndefinedConstant,
kTheHoleConstant,
kTrueConstant,
......
......@@ -136,6 +136,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
// not to call into arbitrary JavaScript, not to throw, and not to deoptimize
// are blacklisted here and can be called without a FrameState.
switch (function) {
case Runtime::kAbort:
case Runtime::kAllocateInTargetSpace:
case Runtime::kCreateIterResultObject:
case Runtime::kDefineDataPropertyInLiteral:
......@@ -144,6 +145,11 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
case Runtime::kFinalizeClassDefinition: // TODO(conradw): Is it safe?
case Runtime::kForInDone:
case Runtime::kForInStep:
case Runtime::kGeneratorSetContext:
case Runtime::kGeneratorGetContinuation:
case Runtime::kGeneratorSetContinuation:
case Runtime::kGeneratorLoadRegister:
case Runtime::kGeneratorStoreRegister:
case Runtime::kGetSuperConstructor:
case Runtime::kIsFunction:
case Runtime::kNewClosure:
......
......@@ -3088,7 +3088,7 @@ bool LinearScanAllocator::TryReuseSpillForPhi(TopLevelLiveRange* range) {
? range->TopLevel()->GetSpillRange()
: data()->AssignSpillRangeToLiveRange(range->TopLevel());
bool merged = first_op_spill->TryMerge(spill_range);
CHECK(merged);
if (!merged) return false;
Spill(range);
return true;
} else if (pos->pos() > range->Start().NextStart()) {
......@@ -3097,7 +3097,7 @@ bool LinearScanAllocator::TryReuseSpillForPhi(TopLevelLiveRange* range) {
? range->TopLevel()->GetSpillRange()
: data()->AssignSpillRangeToLiveRange(range->TopLevel());
bool merged = first_op_spill->TryMerge(spill_range);
CHECK(merged);
if (!merged) return false;
SpillBetween(range, range->Start(), pos->pos());
DCHECK(UnhandledIsSorted());
return true;
......
......@@ -158,6 +158,11 @@ HCompilationJob::Status HCompilationJob::CreateGraphImpl() {
return AbortOptimization(kTooManyParametersLocals);
}
if (IsGeneratorFunction(info()->shared_info()->kind())) {
// Crankshaft does not support generators.
return AbortOptimization(kGenerator);
}
if (FLAG_trace_hydrogen) {
isolate()->GetHTracer()->TraceCompilation(info());
}
......
......@@ -726,6 +726,8 @@ Node* InterpreterAssembler::ExportRegisterFile(Node* array) {
var_index.Bind(Int32Constant(0));
// Iterate over register file and write values into array.
// The mapping of register to array index must match that used in
// BytecodeGraphBuilder::VisitResumeGenerator.
Label loop(this, &var_index), done_loop(this);
Goto(&loop);
Bind(&loop);
......
......@@ -7295,7 +7295,6 @@ class JSGeneratorObject: public JSObject {
DECLARE_CAST(JSGeneratorObject)
// Dispatched behavior.
DECLARE_PRINTER(JSGeneratorObject)
DECLARE_VERIFIER(JSGeneratorObject)
// Magic sentinel values for the continuation.
......
......@@ -129,7 +129,16 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetResumeMode) {
}
// Returns generator continuation as a PC offset, or the magic -1 or 0 values.
RUNTIME_FUNCTION(Runtime_GeneratorSetContext) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
generator->set_context(isolate->context());
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
......@@ -139,6 +148,45 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
}
RUNTIME_FUNCTION(Runtime_GeneratorSetContinuation) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
CONVERT_SMI_ARG_CHECKED(continuation, 1);
generator->set_continuation(continuation);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_GeneratorLoadRegister) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
CONVERT_SMI_ARG_CHECKED(index, 1);
DCHECK(FLAG_ignition && FLAG_ignition_generators);
DCHECK(generator->function()->shared()->HasBytecodeArray());
return generator->operand_stack()->get(index);
}
RUNTIME_FUNCTION(Runtime_GeneratorStoreRegister) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
CONVERT_SMI_ARG_CHECKED(index, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
DCHECK(FLAG_ignition && FLAG_ignition_generators);
DCHECK(generator->function()->shared()->HasBytecodeArray());
generator->operand_stack()->set(index, *value);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
......
......@@ -231,9 +231,13 @@ namespace internal {
F(GeneratorGetFunction, 1, 1) \
F(GeneratorGetReceiver, 1, 1) \
F(GeneratorGetInput, 1, 1) \
F(GeneratorSetContext, 1, 1) \
F(GeneratorGetContinuation, 1, 1) \
F(GeneratorSetContinuation, 2, 1) \
F(GeneratorGetSourcePosition, 1, 1) \
F(GeneratorGetResumeMode, 1, 1)
F(GeneratorGetResumeMode, 1, 1) \
F(GeneratorLoadRegister, 2, 1) \
F(GeneratorStoreRegister, 3, 1)
#ifdef V8_I18N_SUPPORT
#define FOR_EACH_INTRINSIC_I18N(F) \
......
......@@ -192,7 +192,8 @@ Type::bitset BitsetType::Lub(i::Map* map) {
map == heap->no_interceptor_result_sentinel_map() ||
map == heap->termination_exception_map() ||
map == heap->arguments_marker_map() ||
map == heap->optimized_out_map());
map == heap->optimized_out_map() ||
map == heap->stale_register_map());
return kInternal & kTaggedPointer;
}
case HEAP_NUMBER_TYPE:
......
This diff is collapsed.
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