MIPS: Allow the deoptimizer translation to track de-materialized objects.

Port r15087 (63e1626)

Original commit message:
This allows the deoptimizer to materialize objects (e.g. the arguments
object) while deopting without having a consective stack area holding
the object values. The LEnvironment explicitly tracks locations for
these values and preserves them in the translation.

TEST=mjsunit/compiler/inline-arguments
BUG=

Review URL: https://codereview.chromium.org/16846002
Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15097 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
palfia@homejinni.com 2013-06-12 21:46:53 +00:00
parent 2a56e33da7
commit 6124e8f141
3 changed files with 53 additions and 68 deletions

View File

@ -561,27 +561,15 @@ MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
void LCodeGen::WriteTranslation(LEnvironment* environment,
Translation* translation,
int* pushed_arguments_index,
int* pushed_arguments_count) {
Translation* translation) {
if (environment == NULL) return;
// The translation includes one command per value in the environment.
int translation_size = environment->values()->length();
int translation_size = environment->translation_size();
// The output frame height does not include the parameters.
int height = translation_size - environment->parameter_count();
// Function parameters are arguments to the outermost environment. The
// arguments index points to the first element of a sequence of tagged
// values on the stack that represent the arguments. This needs to be
// kept in sync with the LArgumentsElements implementation.
*pushed_arguments_index = -environment->parameter_count();
*pushed_arguments_count = environment->parameter_count();
WriteTranslation(environment->outer(),
translation,
pushed_arguments_index,
pushed_arguments_count);
WriteTranslation(environment->outer(), translation);
bool has_closure_id = !info()->closure().is_null() &&
!info()->closure().is_identical_to(environment->closure());
int closure_id = has_closure_id
@ -613,23 +601,6 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
break;
}
// Inlined frames which push their arguments cause the index to be
// bumped and another stack area to be used for materialization,
// otherwise actual argument values are unknown for inlined frames.
bool arguments_known = true;
int arguments_index = *pushed_arguments_index;
int arguments_count = *pushed_arguments_count;
if (environment->entry() != NULL) {
arguments_known = environment->entry()->arguments_pushed();
arguments_index = arguments_index < 0
? GetStackSlotCount() : arguments_index + arguments_count;
arguments_count = environment->entry()->arguments_count() + 1;
if (environment->entry()->arguments_pushed()) {
*pushed_arguments_index = arguments_index;
*pushed_arguments_count = arguments_count;
}
}
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either
@ -641,10 +612,7 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
AddToTranslation(translation,
environment->spilled_registers()[value->index()],
environment->HasTaggedValueAt(i),
environment->HasUint32ValueAt(i),
arguments_known,
arguments_index,
arguments_count);
environment->HasUint32ValueAt(i));
} else if (
value->IsDoubleRegister() &&
environment->spilled_double_registers()[value->index()] != NULL) {
@ -653,20 +621,36 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
translation,
environment->spilled_double_registers()[value->index()],
false,
false,
arguments_known,
arguments_index,
arguments_count);
false);
}
}
// 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);
ASSERT(environment->spilled_registers() == NULL ||
!value->IsRegister() ||
environment->spilled_registers()[value->index()] == NULL);
ASSERT(environment->spilled_registers() == NULL ||
!value->IsDoubleRegister() ||
environment->spilled_double_registers()[value->index()] == NULL);
AddToTranslation(translation,
value,
environment->HasTaggedValueAt(translation_size + i),
environment->HasUint32ValueAt(translation_size + i));
}
continue;
}
AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
environment->HasUint32ValueAt(i),
arguments_known,
arguments_index,
arguments_count);
environment->HasUint32ValueAt(i));
}
}
@ -674,17 +658,8 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
bool is_uint32,
bool arguments_known,
int arguments_index,
int arguments_count) {
if (op == NULL) {
// TODO(twuerthinger): 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.
translation->StoreArgumentsObject(
arguments_known, arguments_index, arguments_count);
} else if (op->IsStackSlot()) {
bool is_uint32) {
if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
} else if (is_uint32) {
@ -779,8 +754,6 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
int frame_count = 0;
int jsframe_count = 0;
int args_index = 0;
int args_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count;
if (e->frame_type() == JS_FUNCTION) {
@ -788,7 +761,7 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
}
}
Translation translation(&translations_, frame_count, jsframe_count, zone());
WriteTranslation(environment, &translation, &args_index, &args_count);
WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset();
environment->Register(deoptimization_index,

View File

@ -169,10 +169,7 @@ class LCodeGen BASE_EMBEDDED {
int additional_offset);
// Emit frame translation commands for an environment.
void WriteTranslation(LEnvironment* environment,
Translation* translation,
int* arguments_index,
int* arguments_count);
void WriteTranslation(LEnvironment* environment, Translation* translation);
// Declare methods that deal with the individual node types.
#define DECLARE_DO(type) void Do##type(L##type* node);
@ -295,10 +292,7 @@ class LCodeGen BASE_EMBEDDED {
void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
bool is_uint32,
bool arguments_known,
int arguments_index,
int arguments_count);
bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);

View File

@ -933,7 +933,7 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
int value_count = hydrogen_env->length();
int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
LEnvironment* result = new(zone()) LEnvironment(
hydrogen_env->closure(),
hydrogen_env->frame_type(),
@ -944,13 +944,15 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
outer,
hydrogen_env->entry(),
zone());
bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
for (int i = 0; i < value_count; ++i) {
for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
HValue* value = hydrogen_env->values()->at(i);
LOperand* op = NULL;
if (value->IsArgumentsObject()) {
needs_arguments_object_materialization = true;
op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
@ -962,6 +964,22 @@ 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());
ASSERT(HInstruction::cast(value)->IsLinked());
LOperand* op = UseAny(value);
result->AddValue(op,
value->representation(),
value->CheckFlag(HInstruction::kUint32));
}
}
if (hydrogen_env->frame_type() == JS_FUNCTION) {
*argument_index_accumulator = argument_index;
}