[generators] Create the fixed array holding the registers only once.
Instead of replacing the array with an empty one after resuming, overwrite contents with a new Oddball. This will simplify the work to be done by the bytecode graphbuilder and potentially allow for more optimization. (For full-codegen generators, nothing changes.) BUG=v8:4907 LOG=n Review-Url: https://codereview.chromium.org/1923253002 Cr-Commit-Position: refs/heads/master@{#35872}
This commit is contained in:
parent
af41997177
commit
dd47dcb95c
@ -110,6 +110,7 @@ namespace internal {
|
||||
V(kInvalidLhsInCompoundAssignment, "Invalid lhs in compound assignment") \
|
||||
V(kInvalidLhsInCountOperation, "Invalid lhs in count operation") \
|
||||
V(kInvalidMinLength, "Invalid min_length") \
|
||||
V(kInvalidRegisterFileInGenerator, "invalid register file in generator") \
|
||||
V(kJSGlobalObjectNativeContextShouldBeANativeContext, \
|
||||
"JSGlobalObject::native_context should be a native context") \
|
||||
V(kJSGlobalProxyContextShouldNotBeNull, \
|
||||
|
@ -46,6 +46,10 @@ Node* CodeStubAssembler::UndefinedConstant() {
|
||||
return LoadRoot(Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::StaleRegisterConstant() {
|
||||
return LoadRoot(Heap::kStaleRegisterRootIndex);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::Float64Round(Node* x) {
|
||||
Node* one = Float64Constant(1.0);
|
||||
Node* one_half = Float64Constant(0.5);
|
||||
|
@ -38,6 +38,7 @@ class CodeStubAssembler : public compiler::CodeAssembler {
|
||||
compiler::Node* NoContextConstant();
|
||||
compiler::Node* NullConstant();
|
||||
compiler::Node* UndefinedConstant();
|
||||
compiler::Node* StaleRegisterConstant();
|
||||
|
||||
// Float64 operations.
|
||||
compiler::Node* Float64Ceil(compiler::Node* x);
|
||||
|
@ -2290,6 +2290,7 @@ bool Heap::CreateInitialMaps() {
|
||||
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, exception);
|
||||
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, termination_exception);
|
||||
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, optimized_out);
|
||||
ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, stale_register);
|
||||
|
||||
for (unsigned i = 0; i < arraysize(string_type_table); i++) {
|
||||
const StringTypeTable& entry = string_type_table[i];
|
||||
@ -2664,6 +2665,11 @@ void Heap::CreateInitialObjects() {
|
||||
handle(Smi::FromInt(-6), isolate()), false,
|
||||
"undefined", Oddball::kOptimizedOut));
|
||||
|
||||
set_stale_register(
|
||||
*factory->NewOddball(factory->stale_register_map(), "stale_register",
|
||||
handle(Smi::FromInt(-7), isolate()), false,
|
||||
"undefined", Oddball::kStaleRegister));
|
||||
|
||||
for (unsigned i = 0; i < arraysize(constant_string_table); i++) {
|
||||
Handle<String> str =
|
||||
factory->InternalizeUtf8String(constant_string_table[i].contents);
|
||||
|
@ -78,6 +78,7 @@ using v8::MemoryPressureLevel;
|
||||
V(Oddball, exception, Exception) \
|
||||
V(Oddball, termination_exception, TerminationException) \
|
||||
V(Oddball, optimized_out, OptimizedOut) \
|
||||
V(Oddball, stale_register, StaleRegister) \
|
||||
V(FixedArray, number_string_cache, NumberStringCache) \
|
||||
V(Object, instanceof_cache_function, InstanceofCacheFunction) \
|
||||
V(Object, instanceof_cache_map, InstanceofCacheMap) \
|
||||
@ -152,6 +153,7 @@ using v8::MemoryPressureLevel;
|
||||
V(Map, exception_map, ExceptionMap) \
|
||||
V(Map, termination_exception_map, TerminationExceptionMap) \
|
||||
V(Map, optimized_out_map, OptimizedOutMap) \
|
||||
V(Map, stale_register_map, StaleRegisterMap) \
|
||||
V(Map, message_object_map, JSMessageObjectMap) \
|
||||
V(Map, foreign_map, ForeignMap) \
|
||||
V(Map, neander_map, NeanderMap) \
|
||||
|
@ -715,10 +715,12 @@ Node* InterpreterAssembler::RegisterCount() {
|
||||
return Word32Sar(frame_size, Int32Constant(kPointerSizeLog2));
|
||||
}
|
||||
|
||||
Node* InterpreterAssembler::ExportRegisterFile() {
|
||||
Node* register_count = RegisterCount();
|
||||
Node* array =
|
||||
AllocateUninitializedFixedArray(ChangeInt32ToIntPtr(register_count));
|
||||
Node* InterpreterAssembler::ExportRegisterFile(Node* array) {
|
||||
if (FLAG_debug_code) {
|
||||
Node* array_size = SmiUntag(LoadFixedArrayBaseLength(array));
|
||||
AbortIfWordNotEqual(
|
||||
array_size, RegisterCount(), kInvalidRegisterFileInGenerator);
|
||||
}
|
||||
|
||||
Variable var_index(this, MachineRepresentation::kWord32);
|
||||
var_index.Bind(Int32Constant(0));
|
||||
@ -729,16 +731,14 @@ Node* InterpreterAssembler::ExportRegisterFile() {
|
||||
Bind(&loop);
|
||||
{
|
||||
Node* index = var_index.value();
|
||||
Node* condition = Int32LessThan(index, register_count);
|
||||
Node* condition = Int32LessThan(index, RegisterCount());
|
||||
GotoUnless(condition, &done_loop);
|
||||
|
||||
Node* reg_index =
|
||||
Int32Sub(Int32Constant(Register(0).ToOperand()), index);
|
||||
Node* value = LoadRegister(ChangeInt32ToIntPtr(reg_index));
|
||||
|
||||
// No write barrier needed for writing into freshly allocated object.
|
||||
StoreFixedArrayElementNoWriteBarrier(
|
||||
array, ChangeInt32ToIntPtr(index), value);
|
||||
StoreFixedArrayElementInt32Index(array, index, value);
|
||||
|
||||
var_index.Bind(Int32Add(index, Int32Constant(1)));
|
||||
Goto(&loop);
|
||||
@ -749,18 +749,23 @@ Node* InterpreterAssembler::ExportRegisterFile() {
|
||||
}
|
||||
|
||||
Node* InterpreterAssembler::ImportRegisterFile(Node* array) {
|
||||
Node* register_count = RegisterCount();
|
||||
if (FLAG_debug_code) {
|
||||
Node* array_size = SmiUntag(LoadFixedArrayBaseLength(array));
|
||||
AbortIfWordNotEqual(
|
||||
array_size, RegisterCount(), kInvalidRegisterFileInGenerator);
|
||||
}
|
||||
|
||||
Variable var_index(this, MachineRepresentation::kWord32);
|
||||
var_index.Bind(Int32Constant(0));
|
||||
|
||||
// Iterate over array and write values into register file.
|
||||
// Iterate over array and write values into register file. Also erase the
|
||||
// array contents to not keep them alive artificially.
|
||||
Label loop(this, &var_index), done_loop(this);
|
||||
Goto(&loop);
|
||||
Bind(&loop);
|
||||
{
|
||||
Node* index = var_index.value();
|
||||
Node* condition = Int32LessThan(index, register_count);
|
||||
Node* condition = Int32LessThan(index, RegisterCount());
|
||||
GotoUnless(condition, &done_loop);
|
||||
|
||||
Node* value = LoadFixedArrayElementInt32Index(array, index);
|
||||
@ -769,6 +774,8 @@ Node* InterpreterAssembler::ImportRegisterFile(Node* array) {
|
||||
Int32Sub(Int32Constant(Register(0).ToOperand()), index);
|
||||
StoreRegister(value, ChangeInt32ToIntPtr(reg_index));
|
||||
|
||||
StoreFixedArrayElementInt32Index(array, index, StaleRegisterConstant());
|
||||
|
||||
var_index.Bind(Int32Add(index, Int32Constant(1)));
|
||||
Goto(&loop);
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ class InterpreterAssembler : public CodeStubAssembler {
|
||||
// Number of registers.
|
||||
compiler::Node* RegisterCount();
|
||||
|
||||
// Backup/restore register file to/from a fixed array.
|
||||
compiler::Node* ExportRegisterFile();
|
||||
// Backup/restore register file to/from a fixed array of the correct length.
|
||||
compiler::Node* ExportRegisterFile(compiler::Node* array);
|
||||
compiler::Node* ImportRegisterFile(compiler::Node* array);
|
||||
|
||||
// Loads from and stores to the interpreter register file.
|
||||
|
@ -1736,11 +1736,12 @@ void Interpreter::DoSuspendGenerator(InterpreterAssembler* assembler) {
|
||||
Node* generator_reg = __ BytecodeOperandReg(0);
|
||||
Node* generator = __ LoadRegister(generator_reg);
|
||||
|
||||
Node* array = __ ExportRegisterFile();
|
||||
Node* array =
|
||||
__ LoadObjectField(generator, JSGeneratorObject::kOperandStackOffset);
|
||||
Node* context = __ GetContext();
|
||||
Node* state = __ GetAccumulator();
|
||||
|
||||
__ StoreObjectField(generator, JSGeneratorObject::kOperandStackOffset, array);
|
||||
__ ExportRegisterFile(array);
|
||||
__ StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
|
||||
__ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, state);
|
||||
|
||||
@ -1758,8 +1759,6 @@ void Interpreter::DoResumeGenerator(InterpreterAssembler* assembler) {
|
||||
|
||||
__ ImportRegisterFile(
|
||||
__ LoadObjectField(generator, JSGeneratorObject::kOperandStackOffset));
|
||||
__ StoreObjectField(generator, JSGeneratorObject::kOperandStackOffset,
|
||||
__ HeapConstant(isolate_->factory()->empty_fixed_array()));
|
||||
|
||||
Node* old_state =
|
||||
__ LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
|
||||
|
@ -609,7 +609,7 @@ void Oddball::OddballVerify() {
|
||||
CHECK(number->IsSmi());
|
||||
int value = Smi::cast(number)->value();
|
||||
// Hidden oddballs have negative smis.
|
||||
const int kLeastHiddenOddballNumber = -6;
|
||||
const int kLeastHiddenOddballNumber = -7;
|
||||
CHECK_LE(value, 1);
|
||||
CHECK(value >= kLeastHiddenOddballNumber);
|
||||
}
|
||||
@ -634,6 +634,8 @@ void Oddball::OddballVerify() {
|
||||
CHECK(this == heap->exception());
|
||||
} else if (map() == heap->optimized_out_map()) {
|
||||
CHECK(this == heap->optimized_out());
|
||||
} else if (map() == heap->stale_register_map()) {
|
||||
CHECK(this == heap->stale_register());
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -1009,7 +1009,8 @@ template <class C> inline bool Is(Object* obj);
|
||||
V(True) \
|
||||
V(False) \
|
||||
V(ArgumentsMarker) \
|
||||
V(OptimizedOut)
|
||||
V(OptimizedOut) \
|
||||
V(StaleRegister)
|
||||
|
||||
// The element types selection for CreateListFromArrayLike.
|
||||
enum class ElementTypes { kAll, kStringAndSymbol };
|
||||
@ -9493,6 +9494,7 @@ class Oddball: public HeapObject {
|
||||
static const byte kOther = 7;
|
||||
static const byte kException = 8;
|
||||
static const byte kOptimizedOut = 9;
|
||||
static const byte kStaleRegister = 10;
|
||||
|
||||
typedef FixedBodyDescriptor<kToStringOffset, kTypeOfOffset + kPointerSize,
|
||||
kSize> BodyDescriptor;
|
||||
|
@ -19,12 +19,21 @@ RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
|
||||
RUNTIME_ASSERT(function->shared()->is_generator());
|
||||
|
||||
Handle<FixedArray> operand_stack;
|
||||
if (FLAG_ignition && FLAG_ignition_generators) {
|
||||
int size = function->shared()->bytecode_array()->register_count();
|
||||
operand_stack = isolate->factory()->NewFixedArray(size);
|
||||
} else {
|
||||
DCHECK(!function->shared()->HasBytecodeArray());
|
||||
operand_stack = handle(isolate->heap()->empty_fixed_array());
|
||||
}
|
||||
|
||||
Handle<JSGeneratorObject> generator =
|
||||
isolate->factory()->NewJSGeneratorObject(function);
|
||||
generator->set_function(*function);
|
||||
generator->set_context(isolate->context());
|
||||
generator->set_receiver(*receiver);
|
||||
generator->set_operand_stack(isolate->heap()->empty_fixed_array());
|
||||
generator->set_operand_stack(*operand_stack);
|
||||
generator->set_continuation(JSGeneratorObject::kGeneratorExecuting);
|
||||
return *generator;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user