Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(226)

Unified Diff: src/codegen-ia32.cc

Issue 10693: Merged bleeding_edge -r 685:746 into regexp2000. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/regexp2000/
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/codegen-ia32.h ('k') | src/compiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codegen-ia32.cc
===================================================================
--- src/codegen-ia32.cc (revision 746)
+++ src/codegen-ia32.cc (working copy)
@@ -99,9 +99,7 @@
}
-void VirtualFrame::Pop() {
- __ add(Operand(esp), Immediate(kPointerSize));
-}
+void VirtualFrame::Pop() { Drop(1); }
void VirtualFrame::Pop(Register reg) {
@@ -267,10 +265,8 @@
__ int3();
__ bind(&verified_true);
}
-
// Update context local.
__ mov(frame_->Context(), esi);
- // Restore the arguments array pointer, if any.
}
// TODO(1241774): Improve this code:
@@ -310,10 +306,10 @@
// This section stores the pointer to the arguments object that
// was allocated and copied into above. If the address was not
// saved to TOS, we push ecx onto the stack.
-
- // Store the arguments object.
- // This must happen after context initialization because
- // the arguments object may be stored in the context
+ //
+ // Store the arguments object. This must happen after context
+ // initialization because the arguments object may be stored in the
+ // context.
if (arguments_object_allocated) {
ASSERT(scope_->arguments() != NULL);
ASSERT(scope_->arguments_shadow() != NULL);
@@ -341,18 +337,17 @@
frame_->Pop(); // Value is no longer needed.
}
- // Generate code to 'execute' declarations and initialize
- // functions (source elements). In case of an illegal
- // redeclaration we need to handle that instead of processing the
- // declarations.
+ // Generate code to 'execute' declarations and initialize functions
+ // (source elements). In case of an illegal redeclaration we need to
+ // handle that instead of processing the declarations.
if (scope_->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ illegal redeclarations");
scope_->VisitIllegalRedeclaration(this);
} else {
Comment cmnt(masm_, "[ declarations");
ProcessDeclarations(scope_->declarations());
- // Bail out if a stack-overflow exception occurred when
- // processing declarations.
+ // Bail out if a stack-overflow exception occurred when processing
+ // declarations.
if (HasStackOverflow()) return;
}
@@ -448,10 +443,11 @@
// Loads a value on TOS. If it is a boolean value, the result may have been
-// (partially) translated into branches, or it may have set the condition code
-// register. If force_cc is set, the value is forced to set the condition code
-// register and no value is pushed. If the condition code register was set,
-// has_cc() is true and cc_reg_ contains the condition to test for 'true'.
+// (partially) translated into branches, or it may have set the condition
+// code register. If force_cc is set, the value is forced to set the
+// condition code register and no value is pushed. If the condition code
+// register was set, has_cc() is true and cc_reg_ contains the condition to
+// test for 'true'.
void CodeGenerator::LoadCondition(Expression* x,
TypeofState typeof_state,
Label* true_target,
@@ -463,6 +459,14 @@
Visit(x);
}
if (force_cc && !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);
}
ASSERT(has_cc() || !force_cc);
@@ -476,7 +480,6 @@
if (has_cc()) {
// convert cc_reg_ into a bool
-
Label loaded, materialize_true;
__ j(cc_reg_, &materialize_true);
frame_->Push(Immediate(Factory::false_value()));
@@ -604,12 +607,10 @@
// Pop a reference from the stack while preserving TOS.
Comment cmnt(masm_, "[ UnloadReference");
int size = ref->size();
- if (size <= 0) {
- // Do nothing. No popping is necessary.
- } else if (size == 1) {
+ if (size == 1) {
frame_->Pop(eax);
__ mov(frame_->Top(), eax);
- } else {
+ } else if (size > 1) {
frame_->Pop(eax);
frame_->Drop(size);
frame_->Push(eax);
@@ -663,7 +664,7 @@
frame_->Push(eax); // Undo the pop(eax) from above.
ToBooleanStub stub;
__ CallStub(&stub);
- // Convert result (eax) to condition code.
+ // Convert the result (eax) to condition code.
__ test(eax, Operand(eax));
ASSERT(not_equal == not_zero);
@@ -1040,7 +1041,7 @@
} else {
deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode);
__ mov(edx, Operand(eax));
- __ mov(Operand(eax), Immediate(value));
+ __ mov(eax, Immediate(value));
__ sub(eax, Operand(edx));
}
__ j(overflow, deferred->enter(), not_taken);
@@ -1094,7 +1095,7 @@
__ j(not_zero, deferred->enter(), not_taken);
// tag result and store it in TOS (eax)
ASSERT(kSmiTagSize == times_2); // adjust code if not the case
- __ lea(eax, Operand(ebx, times_2, kSmiTag));
+ __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
__ bind(deferred->exit());
frame_->Push(eax);
}
@@ -1123,7 +1124,7 @@
__ j(not_zero, deferred->enter(), not_taken);
// tag result and store it in TOS (eax)
ASSERT(kSmiTagSize == times_2); // adjust code if not the case
- __ lea(eax, Operand(ebx, times_2, kSmiTag));
+ __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
__ bind(deferred->exit());
frame_->Push(eax);
}
@@ -1264,7 +1265,7 @@
CompareStub stub(cc_, strict_);
// Setup parameters and call stub.
__ mov(edx, Operand(eax));
- __ mov(Operand(eax), Immediate(Smi::FromInt(value_)));
+ __ Set(eax, Immediate(Smi::FromInt(value_)));
__ CallStub(&stub);
__ cmp(eax, 0);
// "result" is returned in the flags
@@ -1650,7 +1651,7 @@
__ j(greater_equal, fail_label, not_taken);
// 0 is placeholder.
- __ jmp(Operand(eax, times_2, 0x0, RelocInfo::INTERNAL_REFERENCE));
+ __ jmp(Operand(eax, eax, times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
// calculate address to overwrite later with actual address of table.
int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
@@ -2198,7 +2199,6 @@
frame_->Pop(Operand::StaticVariable(handler_address));
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Next_sp popped.
- // Preserve the TOS in a register across stack manipulation.
frame_->Push(eax);
// --- Finally block ---
@@ -3522,54 +3522,47 @@
Expression* right = node->right();
Token::Value op = node->op();
- // NOTE: To make null checks efficient, we check if either left or
- // right is the literal 'null'. If so, we optimize the code by
- // inlining a null check instead of calling the (very) general
- // runtime routine for checking equality.
-
+ // To make null checks efficient, we check if either left or right is the
+ // literal 'null'. If so, we optimize the code by inlining a null check
+ // instead of calling the (very) general runtime routine for checking
+ // equality.
if (op == Token::EQ || op == Token::EQ_STRICT) {
bool left_is_null =
- left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
+ left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
bool right_is_null =
- right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
- // The 'null' value is only equal to 'null' or 'undefined'.
+ right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
+ // The 'null' value can only be equal to 'null' or 'undefined'.
if (left_is_null || right_is_null) {
Load(left_is_null ? right : left);
- Label exit, undetectable;
frame_->Pop(eax);
__ cmp(eax, Factory::null_value());
- // The 'null' value is only equal to 'undefined' if using
- // non-strict comparisons.
+ // The 'null' value is only equal to 'undefined' if using non-strict
+ // comparisons.
if (op != Token::EQ_STRICT) {
- __ j(equal, &exit);
+ __ j(equal, true_target());
+
__ cmp(eax, Factory::undefined_value());
+ __ j(equal, true_target());
- // NOTE: it can be an undetectable object.
- __ j(equal, &exit);
__ test(eax, Immediate(kSmiTagMask));
+ __ j(equal, false_target());
- __ j(not_equal, &undetectable);
- __ jmp(false_target());
-
- __ bind(&undetectable);
- __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
- __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
- __ and_(ecx, 1 << Map::kIsUndetectable);
- __ cmp(ecx, 1 << Map::kIsUndetectable);
+ // It can be an undetectable object.
+ __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
+ __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
+ __ and_(eax, 1 << Map::kIsUndetectable);
+ __ cmp(eax, 1 << Map::kIsUndetectable);
}
- __ bind(&exit);
-
cc_reg_ = equal;
return;
}
}
- // NOTE: To make typeof testing for natives implemented in
- // JavaScript really efficient, we generate special code for
- // expressions of the form: 'typeof <expression> == <string>'.
-
+ // To make typeof testing for natives implemented in JavaScript really
+ // efficient, we generate special code for expressions of the form:
+ // 'typeof <expression> == <string>'.
UnaryOperation* operation = left->AsUnaryOperation();
if ((op == Token::EQ || op == Token::EQ_STRICT) &&
(operation != NULL && operation->op() == Token::TYPEOF) &&
@@ -3577,7 +3570,7 @@
right->AsLiteral()->handle()->IsString())) {
Handle<String> check(String::cast(*right->AsLiteral()->handle()));
- // Load the operand, move it to register edx, and restore TOS.
+ // Load the operand and move it to register edx.
LoadTypeofExpression(operation->expression());
frame_->Pop(edx);
@@ -3594,7 +3587,7 @@
__ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
- // NOTE: it might be an undetectable string object
+ // It can be an undetectable string object.
__ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
__ and_(ecx, 1 << Map::kIsUndetectable);
__ cmp(ecx, 1 << Map::kIsUndetectable);
@@ -3617,7 +3610,7 @@
__ test(edx, Immediate(kSmiTagMask));
__ j(zero, false_target());
- // NOTE: it can be an undetectable object.
+ // It can be an undetectable object.
__ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
__ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
__ and_(ecx, 1 << Map::kIsUndetectable);
@@ -3641,7 +3634,7 @@
__ cmp(edx, Factory::null_value());
__ j(equal, true_target());
- // NOTE: it might be an undetectable object
+ // It can be an undetectable object.
__ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset));
__ and_(edx, 1 << Map::kIsUndetectable);
__ cmp(edx, 1 << Map::kIsUndetectable);
@@ -3654,8 +3647,8 @@
cc_reg_ = less_equal;
} else {
- // Uncommon case: Typeof testing against a string literal that
- // is never returned from the typeof operator.
+ // Uncommon case: typeof testing against a string literal that is
+ // never returned from the typeof operator.
__ jmp(false_target());
}
return;
@@ -4062,7 +4055,7 @@
__ j(not_zero, slow);
// Tag the result and store it in register eax.
ASSERT(kSmiTagSize == times_2); // adjust code if not the case
- __ lea(eax, Operand(eax, times_2, kSmiTag));
+ __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
break;
case Token::MOD:
@@ -4123,7 +4116,7 @@
}
// Tag the result and store it in register eax.
ASSERT(kSmiTagSize == times_2); // adjust code if not the case
- __ lea(eax, Operand(eax, times_2, kSmiTag));
+ __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
break;
default:
@@ -4250,7 +4243,7 @@
// Tag smi result and return.
ASSERT(kSmiTagSize == times_2); // adjust code if not the case
- __ lea(eax, Operand(eax, times_2, kSmiTag));
+ __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
__ ret(2 * kPointerSize);
// All ops except SHR return a signed int32 that we load in a HeapNumber.
@@ -4984,7 +4977,7 @@
// running with --gc-greedy set.
if (FLAG_gc_greedy) {
Failure* failure = Failure::RetryAfterGC(0);
- __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure)));
+ __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
}
GenerateCore(masm, &throw_normal_exception,
&throw_out_of_memory_exception,
@@ -5002,7 +4995,7 @@
// Do full GC and retry runtime call one final time.
Failure* failure = Failure::InternalError();
- __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure)));
+ __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception,
@@ -5046,7 +5039,7 @@
// exception field in the JSEnv and return a failure sentinel.
ExternalReference pending_exception(Top::k_pending_exception_address);
__ mov(Operand::StaticVariable(pending_exception), eax);
- __ mov(eax, Handle<Failure>(Failure::Exception()));
+ __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
__ jmp(&exit);
// Invoke: Link this frame into the handler chain.
@@ -5068,10 +5061,10 @@
// stub, because the builtin stubs may not have been generated yet.
if (is_construct) {
ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);
- __ mov(Operand(edx), Immediate(construct_entry));
+ __ mov(edx, Immediate(construct_entry));
} else {
ExternalReference entry(Builtins::JSEntryTrampoline);
- __ mov(Operand(edx), Immediate(entry));
+ __ mov(edx, Immediate(entry));
}
__ mov(edx, Operand(edx, 0)); // deref address
__ lea(edx, FieldOperand(edx, Code::kHeaderSize));
« no previous file with comments | « src/codegen-ia32.h ('k') | src/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698