| Index: src/codegen-ia32.cc
|
| ===================================================================
|
| --- src/codegen-ia32.cc (revision 737)
|
| +++ src/codegen-ia32.cc (working copy)
|
| @@ -206,7 +206,7 @@
|
| arguments_object_saved = true;
|
| }
|
| ASSERT(!scope_->is_global_scope()); // no parameters in global scope
|
| - __ mov(eax, frame_->Parameter(i));
|
| + __ mov(eax, frame_->ParameterAt(i));
|
| // Loads ecx with context; used below in RecordWrite.
|
| __ mov(SlotOperand(slot, ecx), eax);
|
| int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
|
| @@ -320,10 +320,10 @@
|
| int index = slot->index();
|
| switch (slot->type()) {
|
| case Slot::PARAMETER:
|
| - return frame_->Parameter(index);
|
| + return frame_->ParameterAt(index);
|
|
|
| case Slot::LOCAL:
|
| - return frame_->Local(index);
|
| + return frame_->LocalAt(index);
|
|
|
| case Slot::CONTEXT: {
|
| // Follow the context chain if necessary.
|
| @@ -377,13 +377,6 @@
|
|
|
| if (force_cc && frame_ != NULL && !has_cc()) {
|
| // Convert the TOS value to a boolean in the condition code register.
|
| - // Visiting an expression may possibly choose neither (a) to leave a
|
| - // value in the condition code register nor (b) to leave a value in TOS
|
| - // (eg, by compiling to only jumps to the targets). In that case the
|
| - // code generated by ToBoolean is wrong because it assumes the value of
|
| - // the expression in TOS. So long as there is always a value in TOS or
|
| - // the condition code register when control falls through to here (there
|
| - // is), the code generated by ToBoolean is dead and therefore safe.
|
| ToBoolean(true_target, false_target);
|
| }
|
|
|
| @@ -398,7 +391,7 @@
|
|
|
| if (has_cc()) {
|
| ASSERT(frame_ != NULL);
|
| - // convert cc_reg_ into a bool
|
| + // Convert cc_reg_ into a boolean value.
|
| JumpTarget loaded(this);
|
| JumpTarget materialize_true(this);
|
| materialize_true.Branch(cc_reg_);
|
| @@ -411,32 +404,32 @@
|
| }
|
|
|
| if (true_target.is_linked() || false_target.is_linked()) {
|
| - // we have at least one condition value
|
| - // that has been "translated" into a branch,
|
| - // thus it needs to be loaded explicitly again
|
| + // We have at least one condition value that has been "translated" into
|
| + // a branch, thus it needs to be loaded explicitly.
|
| JumpTarget loaded(this);
|
| if (frame_ != NULL) {
|
| - loaded.Jump(); // don't lose current TOS
|
| + loaded.Jump(); // Don't lose the current TOS.
|
| }
|
| bool both = true_target.is_linked() && false_target.is_linked();
|
| - // reincarnate "true", if necessary
|
| + // Load "true" if necessary.
|
| if (true_target.is_linked()) {
|
| true_target.Bind();
|
| frame_->Push(Immediate(Factory::true_value()));
|
| }
|
| - // if both "true" and "false" need to be reincarnated,
|
| - // jump across code for "false"
|
| + // If both "true" and "false" need to be reincarnated jump across the
|
| + // code for "false".
|
| if (both) {
|
| loaded.Jump();
|
| }
|
| - // reincarnate "false", if necessary
|
| + // Load "false" if necessary.
|
| if (false_target.is_linked()) {
|
| false_target.Bind();
|
| frame_->Push(Immediate(Factory::false_value()));
|
| }
|
| - // everything is loaded at this point
|
| + // A value is loaded on all paths reaching this point.
|
| loaded.Bind();
|
| }
|
| + ASSERT(frame_ != NULL);
|
| ASSERT(!has_cc());
|
| }
|
|
|
| @@ -1240,7 +1233,8 @@
|
| void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
|
| int position) {
|
| // Push the arguments ("left-to-right") on the stack.
|
| - for (int i = 0; i < args->length(); i++) {
|
| + int arg_count = args->length();
|
| + for (int i = 0; i < arg_count; i++) {
|
| Load(args->at(i));
|
| }
|
|
|
| @@ -1248,8 +1242,8 @@
|
| __ RecordPosition(position);
|
|
|
| // Use the shared code stub to call the function.
|
| - CallFunctionStub call_function(args->length());
|
| - frame_->CallStub(&call_function, args->length() + 1);
|
| + CallFunctionStub call_function(arg_count);
|
| + frame_->CallStub(&call_function, arg_count + 1);
|
|
|
| // Restore context and pop function from the stack.
|
| __ mov(esi, frame_->Context());
|
| @@ -1387,8 +1381,8 @@
|
|
|
| void CodeGenerator::VisitIfStatement(IfStatement* node) {
|
| Comment cmnt(masm_, "[ IfStatement");
|
| - // Generate different code depending on which
|
| - // parts of the if statement are present or not.
|
| + // Generate different code depending on which parts of the if statement
|
| + // are present or not.
|
| bool has_then_stm = node->HasThenStatement();
|
| bool has_else_stm = node->HasElseStatement();
|
|
|
| @@ -1659,54 +1653,54 @@
|
| JumpTarget fall_through(this);
|
| JumpTarget default_entry(this);
|
| JumpTarget default_exit(this);
|
| -
|
| ZoneList<CaseClause*>* cases = node->cases();
|
| int length = cases->length();
|
| CaseClause* default_clause = NULL;
|
|
|
| for (int i = 0; i < length; i++) {
|
| CaseClause* clause = cases->at(i);
|
| -
|
| if (clause->is_default()) {
|
| + // Remember the default clause and compile it at the end.
|
| default_clause = clause;
|
| - } else {
|
| - Comment cmnt(masm_, "[ Case clause");
|
| + continue;
|
| + }
|
|
|
| - // Compile the test.
|
| - next_test.Bind();
|
| - next_test.Unuse();
|
| - // Duplicate TOS.
|
| - __ mov(eax, frame_->Top());
|
| - frame_->Push(eax);
|
| - Load(clause->label());
|
| - Comparison(equal, true);
|
| - Branch(false, &next_test);
|
| + Comment cmnt(masm_, "[ Case clause");
|
| + // Compile the test.
|
| + next_test.Bind();
|
| + next_test.Unuse();
|
| + // Duplicate TOS.
|
| + __ mov(eax, frame_->Top());
|
| + frame_->Push(eax);
|
| + Load(clause->label());
|
| + Comparison(equal, true);
|
| + Branch(false, &next_test);
|
|
|
| - // Before entering the body, remove the switch value from the stack.
|
| - frame_->Drop();
|
| + // Before entering the body from the test, remove the switch value from
|
| + // the stack.
|
| + frame_->Drop();
|
|
|
| - // Label the body so that fall through is enabled.
|
| - if (i > 0 && cases->at(i - 1)->is_default()) {
|
| - default_exit.Bind();
|
| + // Label the body so that fall through is enabled.
|
| + if (i > 0 && cases->at(i - 1)->is_default()) {
|
| + default_exit.Bind();
|
| + } else {
|
| + fall_through.Bind();
|
| + fall_through.Unuse();
|
| + }
|
| + VisitStatements(clause->statements());
|
| +
|
| + // If control flow can fall through from the body, jump to the next body
|
| + // or the end of the statement.
|
| + if (frame_ != NULL) {
|
| + if (i < length - 1 && cases->at(i + 1)->is_default()) {
|
| + default_entry.Jump();
|
| } else {
|
| - fall_through.Bind();
|
| - fall_through.Unuse();
|
| + fall_through.Jump();
|
| }
|
| - VisitStatements(clause->statements());
|
| -
|
| - // If control flow can fall through from the body jump to the
|
| - // next body or end of the statement.
|
| - if (frame_ != NULL) {
|
| - if (i < length - 1 && cases->at(i + 1)->is_default()) {
|
| - default_entry.Jump();
|
| - } else {
|
| - fall_through.Jump();
|
| - }
|
| - }
|
| }
|
| }
|
|
|
| - // The final test removes the switch value.
|
| + // The final "test" removes the switch value.
|
| next_test.Bind();
|
| frame_->Drop();
|
|
|
| @@ -1759,7 +1753,6 @@
|
| switch (node->type()) {
|
| case LoopStatement::DO_LOOP: {
|
| JumpTarget body(this);
|
| -
|
| IncrementLoopNesting();
|
| // Label the body.
|
| if (info == ALWAYS_TRUE) {
|
| @@ -1773,6 +1766,7 @@
|
| CheckStack(); // TODO(1222600): ignore if body contains calls.
|
| Visit(node->body());
|
|
|
| + // Compile the "test".
|
| if (info == ALWAYS_TRUE) {
|
| if (frame_ != NULL) {
|
| // If control flow can fall off the end of the body, jump back to
|
| @@ -1787,9 +1781,8 @@
|
| }
|
| } else {
|
| ASSERT(info == DONT_KNOW);
|
| - // We have to compile the test expression if we don't know its value
|
| - // and it can be reached by control flow falling out of the body or
|
| - // via continue.
|
| + // We have to compile the test expression if it can be reached by
|
| + // control flow falling out of the body or via continue.
|
| if (frame_ != NULL || node->continue_target()->is_linked()) {
|
| node->continue_target()->Bind();
|
| LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
|
| @@ -1805,9 +1798,7 @@
|
| }
|
|
|
| case LoopStatement::WHILE_LOOP: {
|
| -
|
| JumpTarget body(this);
|
| -
|
| IncrementLoopNesting();
|
| // Generate the loop header.
|
| if (info == ALWAYS_TRUE) {
|
| @@ -1926,13 +1917,13 @@
|
| node->break_target()->set_code_generator(this);
|
| node->continue_target()->set_code_generator(this);
|
|
|
| - JumpTarget entry(this);
|
| - JumpTarget cleanup(this);
|
| - JumpTarget exit(this);
|
| JumpTarget primitive(this);
|
| JumpTarget jsobject(this);
|
| - JumpTarget end_del_check(this);
|
| JumpTarget fixed_array(this);
|
| + JumpTarget entry(this);
|
| + JumpTarget end_del_check(this);
|
| + JumpTarget cleanup(this);
|
| + JumpTarget exit(this);
|
|
|
| // Get the object to enumerate over (converted to JSObject).
|
| Load(node->enumerable());
|
| @@ -1968,9 +1959,7 @@
|
| frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
|
| // function call returns the value in eax, which is where we want it below
|
|
|
| -
|
| jsobject.Bind();
|
| -
|
| // Get the set of properties (as a FixedArray or Map).
|
| // eax: value to be iterated over
|
| frame_->Push(eax); // push the object being iterated over (slot 4)
|
| @@ -2004,9 +1993,7 @@
|
| frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0
|
| entry.Jump();
|
|
|
| -
|
| fixed_array.Bind();
|
| -
|
| // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast)
|
| frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 3
|
| frame_->Push(eax); // <- slot 2
|
| @@ -2019,7 +2006,6 @@
|
|
|
| // Condition.
|
| entry.Bind();
|
| -
|
| __ mov(eax, frame_->ElementAt(0)); // load the current count
|
| __ cmp(eax, frame_->ElementAt(1)); // compare to the array length
|
| cleanup.Branch(above_equal);
|
| @@ -2054,8 +2040,8 @@
|
| node->continue_target()->Branch(equal);
|
|
|
| end_del_check.Bind();
|
| - // Store the entry in the 'each' expression and take another spin in the loop.
|
| - // edx: i'th entry of the enum cache (or string there of)
|
| + // Store the entry in the 'each' expression and take another spin in the
|
| + // loop. edx: i'th entry of the enum cache (or string there of)
|
| frame_->Push(ebx);
|
| { Reference each(this, node->each());
|
| if (!each.is_illegal()) {
|
| @@ -2210,8 +2196,7 @@
|
| frame_->Pop(Operand::StaticVariable(handler_address));
|
| frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
|
| // next_sp popped.
|
| - JumpTarget* original_target = shadows[i]->original_target();
|
| - original_target->Jump();
|
| + shadows[i]->original_target()->Jump();
|
| }
|
| }
|
|
|
| @@ -2227,7 +2212,6 @@
|
| // break/continue from within the try block.
|
| enum { FALLING, THROWING, JUMPING };
|
|
|
| - JumpTarget exit(this);
|
| JumpTarget unlink(this);
|
| JumpTarget try_block(this);
|
| JumpTarget finally_block(this);
|
| @@ -2342,6 +2326,7 @@
|
|
|
| break_stack_height_ -= kFinallyStackSize;
|
| if (frame_ != NULL) {
|
| + JumpTarget exit(this);
|
| // Restore state and return value or faked TOS.
|
| frame_->Pop(ecx);
|
| frame_->Pop(eax);
|
| @@ -2644,7 +2629,7 @@
|
| Load(property->value());
|
| frame_->Pop(eax);
|
| __ Set(ecx, Immediate(key));
|
| - frame_->CallCode(ic, RelocInfo::CODE_TARGET, 0);
|
| + frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
|
| frame_->Drop();
|
| // Ignore result.
|
| break;
|
| @@ -2842,14 +2827,16 @@
|
| LoadGlobal();
|
|
|
| // Load the arguments.
|
| - for (int i = 0; i < args->length(); i++) {
|
| + int arg_count = args->length();
|
| + for (int i = 0; i < arg_count; i++) {
|
| Load(args->at(i));
|
| }
|
|
|
| // Setup the receiver register and call the IC initialization code.
|
| - Handle<Code> stub = ComputeCallInitialize(args->length());
|
| + Handle<Code> stub = ComputeCallInitialize(arg_count);
|
| __ RecordPosition(node->position());
|
| - frame_->CallCode(stub, RelocInfo::CODE_TARGET_CONTEXT, args->length() + 1);
|
| + frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
|
| + arg_count + 1);
|
| __ mov(esi, frame_->Context());
|
|
|
| // Overwrite the function on the stack with the result.
|
| @@ -2888,12 +2875,15 @@
|
| Load(property->obj());
|
|
|
| // Load the arguments.
|
| - for (int i = 0; i < args->length(); i++) Load(args->at(i));
|
| + int arg_count = args->length();
|
| + for (int i = 0; i < arg_count; i++) {
|
| + Load(args->at(i));
|
| + }
|
|
|
| // Call the IC initialization code.
|
| - Handle<Code> stub = ComputeCallInitialize(args->length());
|
| + Handle<Code> stub = ComputeCallInitialize(arg_count);
|
| __ RecordPosition(node->position());
|
| - frame_->CallCode(stub, RelocInfo::CODE_TARGET, args->length() + 1);
|
| + frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
|
| __ mov(esi, frame_->Context());
|
|
|
| // Overwrite the function on the stack with the result.
|
| @@ -2950,24 +2940,25 @@
|
|
|
| // Push the arguments ("left-to-right") on the stack.
|
| ZoneList<Expression*>* args = node->arguments();
|
| - for (int i = 0; i < args->length(); i++) {
|
| + int arg_count = args->length();
|
| + for (int i = 0; i < arg_count; i++) {
|
| Load(args->at(i));
|
| }
|
|
|
| // Constructors are called with the number of arguments in register
|
| // eax for now. Another option would be to have separate construct
|
| // call trampolines per different arguments counts encountered.
|
| - __ Set(eax, Immediate(args->length()));
|
| + __ Set(eax, Immediate(arg_count));
|
|
|
| // Load the function into temporary function slot as per calling
|
| // convention.
|
| - __ mov(edi, frame_->ElementAt(args->length() + 1));
|
| + __ mov(edi, frame_->ElementAt(arg_count + 1));
|
|
|
| // Call the construct call builtin that handles allocation and
|
| // constructor invocation.
|
| __ RecordPosition(node->position());
|
| Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
|
| - frame_->CallCode(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1);
|
| + frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1);
|
| // Discard the function and "push" the newly created object.
|
| __ mov(frame_->Top(), eax);
|
| }
|
| @@ -3242,20 +3233,21 @@
|
| }
|
|
|
| // Push the arguments ("left-to-right").
|
| - for (int i = 0; i < args->length(); i++) {
|
| + int arg_count = args->length();
|
| + for (int i = 0; i < arg_count; i++) {
|
| Load(args->at(i));
|
| }
|
|
|
| if (function == NULL) {
|
| // Call the JS runtime function.
|
| - Handle<Code> stub = ComputeCallInitialize(args->length());
|
| + Handle<Code> stub = ComputeCallInitialize(arg_count);
|
| __ Set(eax, Immediate(args->length()));
|
| - frame_->CallCode(stub, RelocInfo::CODE_TARGET, args->length() + 1);
|
| + frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
|
| __ mov(esi, frame_->Context());
|
| __ mov(frame_->Top(), eax);
|
| } else {
|
| // Call the C runtime function.
|
| - frame_->CallRuntime(function, args->length());
|
| + frame_->CallRuntime(function, arg_count);
|
| frame_->Push(eax);
|
| }
|
| }
|
| @@ -3968,9 +3960,9 @@
|
| Variable* var = expression_->AsVariableProxy()->AsVariable();
|
| if (var != NULL) {
|
| ASSERT(var->is_global());
|
| - frame->CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
|
| + frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
|
| } else {
|
| - frame->CallCode(ic, RelocInfo::CODE_TARGET, 0);
|
| + frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
|
| }
|
| frame->Push(eax); // IC call leaves result in eax, push it out
|
| break;
|
| @@ -3988,9 +3980,9 @@
|
| Variable* var = expression_->AsVariableProxy()->AsVariable();
|
| if (var != NULL) {
|
| ASSERT(var->is_global());
|
| - frame->CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
|
| + frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
|
| } else {
|
| - frame->CallCode(ic, RelocInfo::CODE_TARGET, 0);
|
| + frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
|
| }
|
| frame->Push(eax); // IC call leaves result in eax, push it out
|
| break;
|
| @@ -4094,7 +4086,7 @@
|
| frame->Pop(eax);
|
| // Setup the name register.
|
| __ mov(ecx, name);
|
| - frame->CallCode(ic, RelocInfo::CODE_TARGET, 0);
|
| + frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
|
| frame->Push(eax); // IC call leaves result in eax, push it out
|
| break;
|
| }
|
| @@ -4108,7 +4100,7 @@
|
| Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
| // TODO(1222589): Make the IC grab the values from the stack.
|
| frame->Pop(eax);
|
| - frame->CallCode(ic, RelocInfo::CODE_TARGET, 0);
|
| + frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
|
| frame->Push(eax); // IC call leaves result in eax, push it out
|
| break;
|
| }
|
|
|