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

Unified Diff: src/ia32/code-stubs-ia32.cc

Issue 7473028: Implement a type recording ToBoolean IC. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 5 months 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
« src/code-stubs.cc ('K') | « src/debug.cc ('k') | src/ic.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/code-stubs-ia32.cc
===================================================================
--- src/ia32/code-stubs-ia32.cc (revision 8701)
+++ src/ia32/code-stubs-ia32.cc (working copy)
@@ -236,72 +236,163 @@
}
-// The stub returns zero for false, and a non-zero value for true.
+// The stub expects its argument on the stack and returns its result in tos_:
+// zero for false, and a non-zero value for true.
void ToBooleanStub::Generate(MacroAssembler* masm) {
- Label false_result, true_result, not_string;
+ Label patch;
Factory* factory = masm->isolate()->factory();
const Register map = edx;
- __ mov(eax, Operand(esp, 1 * kPointerSize));
+ if (!types_.IsEmpty()) {
+ __ mov(eax, Operand(esp, 1 * kPointerSize));
+ }
// undefined -> false
- __ cmp(eax, factory->undefined_value());
- __ j(equal, &false_result);
+ CheckOddball(masm, UNDEFINED, factory->undefined_value(), false, &patch);
// Boolean -> its value
- __ cmp(eax, factory->false_value());
- __ j(equal, &false_result);
- __ cmp(eax, factory->true_value());
- __ j(equal, &true_result);
+ CheckOddball(masm, BOOLEAN, factory->false_value(), false, &patch);
+ CheckOddball(masm, BOOLEAN, factory->true_value(), true, &patch);
- // Smis: 0 -> false, all other -> true
- __ test(eax, Operand(eax));
- __ j(zero, &false_result);
- __ JumpIfSmi(eax, &true_result);
-
// 'null' -> false.
- __ cmp(eax, factory->null_value());
- __ j(equal, &false_result, Label::kNear);
+ CheckOddball(masm, NULL_TYPE, factory->null_value(), false, &patch);
- // Get the map of the heap object.
- __ mov(map, FieldOperand(eax, HeapObject::kMapOffset));
+ bool need_map =
+ types_.Contains(UNDETECTABLE) |
+ types_.Contains(SPEC_OBJECT) |
+ types_.Contains(STRING) |
+ types_.Contains(HEAP_NUMBER) |
+ types_.Contains(INTERNAL_OBJECT);
- // Undetectable -> false.
- __ test_b(FieldOperand(map, Map::kBitFieldOffset),
- 1 << Map::kIsUndetectable);
- __ j(not_zero, &false_result, Label::kNear);
+ if (types_.Contains(SMI)) {
+ // Smis: 0 -> false, all other -> true
+ Label not_smi;
+ __ JumpIfNotSmi(eax, &not_smi, Label::kNear);
+ __ ret(1 * kPointerSize); // eax contains the correct value already
+ __ bind(&not_smi);
+ } else if (need_map) {
+ // If we need a map later and have a Smi -> patch.
+ __ JumpIfSmi(eax, &patch, Label::kNear);
+ }
- // JavaScript object -> true.
- __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
- __ j(above_equal, &true_result, Label::kNear);
+ if (need_map) {
+ __ mov(map, FieldOperand(eax, HeapObject::kMapOffset));
- // String value -> false iff empty.
- __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
- __ j(above_equal, &not_string, Label::kNear);
- __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0));
- __ j(zero, &false_result, Label::kNear);
- __ jmp(&true_result, Label::kNear);
+ // Everything with a map could be undetectable, so check this now.
+ __ test_b(FieldOperand(map, Map::kBitFieldOffset),
+ 1 << Map::kIsUndetectable);
+ if (types_.Contains(UNDETECTABLE)) {
+ // Undetectable -> false.
+ Label not_undetectable;
+ __ j(zero, &not_undetectable, Label::kNear);
+ __ xor_(tos_, Operand(tos_));
Vitaly Repeshko 2011/07/21 13:17:23 The macro assembler has Set macro that emits the o
Sven Panne 2011/07/21 13:49:28 I didn't know that one, thanks. :-)
+ __ ret(1 * kPointerSize);
+ __ bind(&not_undetectable);
+ } else {
+ // We've seen an undetectable value for the first time -> patch.
+ __ j(not_zero, &patch, Label::kNear);
+ }
+ }
- __ bind(&not_string);
- // HeapNumber -> false iff +0, -0, or NaN.
- __ cmp(map, factory->heap_number_map());
- __ j(not_equal, &true_result, Label::kNear);
- __ fldz();
- __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
- __ FCmp();
- __ j(zero, &false_result, Label::kNear);
- // Fall through to |true_result|.
+ if (types_.Contains(SPEC_OBJECT)) {
+ // spec object -> true.
+ Label not_js_object;
+ __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
+ __ j(below, &not_js_object, Label::kNear);
+ __ mov(tos_, 1);
+ __ ret(1 * kPointerSize);
+ __ bind(&not_js_object);
+ } else if (types_.Contains(INTERNAL_OBJECT)) {
+ // We've seen a spec object for the first time -> patch.
+ __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
+ __ j(above_equal, &patch, Label::kNear);
+ }
- // Return 1/0 for true/false in tos_.
- __ bind(&true_result);
- __ mov(tos_, 1);
- __ ret(1 * kPointerSize);
- __ bind(&false_result);
- __ mov(tos_, 0);
- __ ret(1 * kPointerSize);
+ if (types_.Contains(STRING)) {
+ // String value -> false iff empty.
+ Label not_string;
+ __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
+ __ j(above_equal, &not_string, Label::kNear);
+ __ mov(eax, FieldOperand(eax, String::kLengthOffset));
danno 2011/07/21 12:39:07 eax -> tos_?
Sven Panne 2011/07/21 13:49:28 Ooops, fixed, same for Smi part above.
+ __ ret(1 * kPointerSize); // the string length is OK as the return value
+ __ bind(&not_string);
+ } else if (types_.Contains(INTERNAL_OBJECT)) {
+ // We've seen a string for the first time -> patch
+ __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
+ __ j(below, &patch, Label::kNear);
+ }
+
+ if (types_.Contains(HEAP_NUMBER)) {
+ // heap number -> false iff +0, -0, or NaN.
+ Label not_heap_number, false_result;
+ __ cmp(map, factory->heap_number_map());
+ __ j(not_equal, &not_heap_number, Label::kNear);
+ __ fldz();
+ __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+ __ FCmp();
+ __ j(zero, &false_result, Label::kNear);
+ __ mov(tos_, 1);
+ __ ret(1 * kPointerSize);
+ __ bind(&false_result);
+ __ xor_(tos_, Operand(tos_));
+ __ ret(1 * kPointerSize);
+ __ bind(&not_heap_number);
+ } else if (types_.Contains(INTERNAL_OBJECT)) {
+ // We've seen a heap number for the first time -> patch
+ __ cmp(map, factory->heap_number_map());
+ __ j(equal, &patch, Label::kNear);
+ }
+
+ if (types_.Contains(INTERNAL_OBJECT)) {
fschneider 2011/07/21 13:16:44 Can you explain why we need the INTERNAL_OBJECT ca
Sven Panne 2011/07/21 13:49:28 While we probably can't encounter internal objects
+ // internal objects -> true
+ __ mov(tos_, 1);
+ __ ret(1 * kPointerSize);
+ }
+
+ __ bind(&patch);
+ GenerateTypeTransition(masm);
}
+void ToBooleanStub::CheckOddball(MacroAssembler* masm,
+ Type type,
+ Handle<Object> value,
+ bool result,
+ Label* patch) {
+ __ cmp(eax, value);
danno 2011/07/21 12:39:07 This should be duplicated in the two if branches s
Sven Panne 2011/07/21 13:49:28 Done.
+ if (types_.Contains(type)) {
+ // If we see an expected oddball, return its ToBoolean value tos_.
+ Label different_value;
+ __ j(not_equal, &different_value, Label::kNear);
+ if (result) {
+ __ mov(tos_, 1);
+ } else {
+ __ xor_(tos_, Operand(tos_));
+ }
+ __ ret(1 * kPointerSize);
+ __ bind(&different_value);
+ } else if (types_.Contains(INTERNAL_OBJECT)) {
+ // If we see an unexpected oddball and handle internal objects, we must
+ // patch because the code for internal objects doesn't handle it explictly.
+ __ j(equal, patch);
+ }
+}
+
+
+void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
+ __ pop(ecx); // Get return address, operand is now on top of stack.
+ __ push(Immediate(Smi::FromInt(tos_.code())));
+ __ push(Immediate(Smi::FromInt(types_.ToInt())));
+ __ push(ecx); // Push return address.
+ // Patch the caller to an appropriate specialized stub and return the
+ // operation result to the caller of the stub.
+ __ TailCallExternalReference(
+ ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
+ 3,
+ 1);
+}
+
+
class FloatingPointHelper : public AllStatic {
public:
enum ArgLocation {
« src/code-stubs.cc ('K') | « src/debug.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698