[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:
neis 2016-04-28 07:54:39 -07:00 committed by Commit bot
parent af41997177
commit dd47dcb95c
11 changed files with 53 additions and 20 deletions

View File

@ -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, \

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) \

View File

@ -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);
}

View File

@ -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.

View 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);

View File

@ -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();
}

View File

@ -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;

View File

@ -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;
}