MIPS: First implementation of allocation elimination in Hydrogen.
Port r16098 (328ff5f7) Original commit message: This change implements a simple data-flow analysis pass over captured objects to the existing escape analysis. It tracks the state of values in the Hydrogen graph through CapturedObject marker instructions that are used to construct an appropriate translation for the deoptimizer to be able to materialize these objects again. This can be considered a combination of scalar replacement of loads and stores on captured objects and sinking of unused allocations. TEST=mjsunit/compiler/escape-analysis BUG= Review URL: https://codereview.chromium.org/22580003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16107 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
371ac893f9
commit
5021e72675
@ -591,37 +591,57 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
|
||||
break;
|
||||
}
|
||||
|
||||
int object_index = 0;
|
||||
int dematerialized_index = 0;
|
||||
for (int i = 0; i < translation_size; ++i) {
|
||||
LOperand* value = environment->values()->at(i);
|
||||
|
||||
// TODO(mstarzinger): Introduce marker operands to indicate that this value
|
||||
// is not present and must be reconstructed from the deoptimizer. Currently
|
||||
// this is only used for the arguments object.
|
||||
if (value == NULL) {
|
||||
int arguments_count = environment->values()->length() - translation_size;
|
||||
translation->BeginArgumentsObject(arguments_count);
|
||||
for (int i = 0; i < arguments_count; ++i) {
|
||||
LOperand* value = environment->values()->at(translation_size + i);
|
||||
AddToTranslation(translation,
|
||||
value,
|
||||
environment->HasTaggedValueAt(translation_size + i),
|
||||
environment->HasUint32ValueAt(translation_size + i));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
AddToTranslation(translation,
|
||||
AddToTranslation(environment,
|
||||
translation,
|
||||
value,
|
||||
environment->HasTaggedValueAt(i),
|
||||
environment->HasUint32ValueAt(i));
|
||||
environment->HasUint32ValueAt(i),
|
||||
&object_index,
|
||||
&dematerialized_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::AddToTranslation(Translation* translation,
|
||||
void LCodeGen::AddToTranslation(LEnvironment* environment,
|
||||
Translation* translation,
|
||||
LOperand* op,
|
||||
bool is_tagged,
|
||||
bool is_uint32) {
|
||||
bool is_uint32,
|
||||
int* object_index_pointer,
|
||||
int* dematerialized_index_pointer) {
|
||||
if (op == LEnvironment::materialization_marker()) {
|
||||
int object_index = (*object_index_pointer)++;
|
||||
if (environment->ObjectIsDuplicateAt(object_index)) {
|
||||
int dupe_of = environment->ObjectDuplicateOfAt(object_index);
|
||||
translation->DuplicateObject(dupe_of);
|
||||
return;
|
||||
}
|
||||
int object_length = environment->ObjectLengthAt(object_index);
|
||||
if (environment->ObjectIsArgumentsAt(object_index)) {
|
||||
translation->BeginArgumentsObject(object_length);
|
||||
} else {
|
||||
translation->BeginCapturedObject(object_length);
|
||||
}
|
||||
int dematerialized_index = *dematerialized_index_pointer;
|
||||
int env_offset = environment->translation_size() + dematerialized_index;
|
||||
*dematerialized_index_pointer += object_length;
|
||||
for (int i = 0; i < object_length; ++i) {
|
||||
LOperand* value = environment->values()->at(env_offset + i);
|
||||
AddToTranslation(environment,
|
||||
translation,
|
||||
value,
|
||||
environment->HasTaggedValueAt(env_offset + i),
|
||||
environment->HasUint32ValueAt(env_offset + i),
|
||||
object_index_pointer,
|
||||
dematerialized_index_pointer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (op->IsStackSlot()) {
|
||||
if (is_tagged) {
|
||||
translation->StoreStackSlot(op->index());
|
||||
|
@ -290,10 +290,13 @@ class LCodeGen BASE_EMBEDDED {
|
||||
Register src1 = zero_reg,
|
||||
const Operand& src2 = Operand(zero_reg));
|
||||
|
||||
void AddToTranslation(Translation* translation,
|
||||
void AddToTranslation(LEnvironment* environment,
|
||||
Translation* translation,
|
||||
LOperand* op,
|
||||
bool is_tagged,
|
||||
bool is_uint32);
|
||||
bool is_uint32,
|
||||
int* object_index_pointer,
|
||||
int* dematerialized_index_pointer);
|
||||
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
|
||||
void PopulateDeoptimizationData(Handle<Code> code);
|
||||
int DefineDeoptimizationLiteral(Handle<Object> literal);
|
||||
|
@ -598,8 +598,10 @@ LInstruction* LChunkBuilder::DefineFixedDouble(
|
||||
LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
|
||||
HEnvironment* hydrogen_env = current_block_->last_environment();
|
||||
int argument_index_accumulator = 0;
|
||||
ZoneList<HValue*> objects_to_materialize(0, zone());
|
||||
instr->set_environment(CreateEnvironment(hydrogen_env,
|
||||
&argument_index_accumulator));
|
||||
&argument_index_accumulator,
|
||||
&objects_to_materialize));
|
||||
return instr;
|
||||
}
|
||||
|
||||
@ -903,11 +905,13 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
|
||||
|
||||
LEnvironment* LChunkBuilder::CreateEnvironment(
|
||||
HEnvironment* hydrogen_env,
|
||||
int* argument_index_accumulator) {
|
||||
int* argument_index_accumulator,
|
||||
ZoneList<HValue*>* objects_to_materialize) {
|
||||
if (hydrogen_env == NULL) return NULL;
|
||||
|
||||
LEnvironment* outer =
|
||||
CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
|
||||
LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(),
|
||||
argument_index_accumulator,
|
||||
objects_to_materialize);
|
||||
BailoutId ast_id = hydrogen_env->ast_id();
|
||||
ASSERT(!ast_id.IsNone() ||
|
||||
hydrogen_env->frame_type() != JS_FUNCTION);
|
||||
@ -922,16 +926,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
|
||||
outer,
|
||||
hydrogen_env->entry(),
|
||||
zone());
|
||||
bool needs_arguments_object_materialization = false;
|
||||
int argument_index = *argument_index_accumulator;
|
||||
int object_index = objects_to_materialize->length();
|
||||
for (int i = 0; i < hydrogen_env->length(); ++i) {
|
||||
if (hydrogen_env->is_special_index(i)) continue;
|
||||
|
||||
LOperand* op;
|
||||
HValue* value = hydrogen_env->values()->at(i);
|
||||
LOperand* op = NULL;
|
||||
if (value->IsArgumentsObject()) {
|
||||
needs_arguments_object_materialization = true;
|
||||
op = NULL;
|
||||
if (value->IsArgumentsObject() || value->IsCapturedObject()) {
|
||||
objects_to_materialize->Add(value, zone());
|
||||
op = LEnvironment::materialization_marker();
|
||||
} else if (value->IsPushArgument()) {
|
||||
op = new(zone()) LArgument(argument_index++);
|
||||
} else {
|
||||
@ -942,15 +946,33 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
|
||||
value->CheckFlag(HInstruction::kUint32));
|
||||
}
|
||||
|
||||
if (needs_arguments_object_materialization) {
|
||||
HArgumentsObject* arguments = hydrogen_env->entry() == NULL
|
||||
? graph()->GetArgumentsObject()
|
||||
: hydrogen_env->entry()->arguments_object();
|
||||
ASSERT(arguments->IsLinked());
|
||||
for (int i = 1; i < arguments->arguments_count(); ++i) {
|
||||
HValue* value = arguments->arguments_values()->at(i);
|
||||
ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
|
||||
LOperand* op = UseAny(value);
|
||||
for (int i = object_index; i < objects_to_materialize->length(); ++i) {
|
||||
HValue* object_to_materialize = objects_to_materialize->at(i);
|
||||
int previously_materialized_object = -1;
|
||||
for (int prev = 0; prev < i; ++prev) {
|
||||
if (objects_to_materialize->at(prev) == objects_to_materialize->at(i)) {
|
||||
previously_materialized_object = prev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int length = object_to_materialize->OperandCount();
|
||||
bool is_arguments = object_to_materialize->IsArgumentsObject();
|
||||
if (previously_materialized_object >= 0) {
|
||||
result->AddDuplicateObject(previously_materialized_object);
|
||||
continue;
|
||||
} else {
|
||||
result->AddNewObject(is_arguments ? length - 1 : length, is_arguments);
|
||||
}
|
||||
for (int i = is_arguments ? 1 : 0; i < length; ++i) {
|
||||
LOperand* op;
|
||||
HValue* value = object_to_materialize->OperandAt(i);
|
||||
if (value->IsArgumentsObject() || value->IsCapturedObject()) {
|
||||
objects_to_materialize->Add(value, zone());
|
||||
op = LEnvironment::materialization_marker();
|
||||
} else {
|
||||
ASSERT(!value->IsPushArgument());
|
||||
op = UseAny(value);
|
||||
}
|
||||
result->AddValue(op,
|
||||
value->representation(),
|
||||
value->CheckFlag(HInstruction::kUint32));
|
||||
@ -2358,6 +2380,12 @@ LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
|
||||
// There are no real uses of a captured object.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
|
||||
info()->MarkAsRequiresFrame();
|
||||
LOperand* args = UseRegister(instr->arguments());
|
||||
|
@ -2690,7 +2690,8 @@ class LChunkBuilder BASE_EMBEDDED {
|
||||
CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
|
||||
|
||||
LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
|
||||
int* argument_index_accumulator);
|
||||
int* argument_index_accumulator,
|
||||
ZoneList<HValue*>* objects_to_materialize);
|
||||
|
||||
void VisitInstruction(HInstruction* current);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user