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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« src/code-stubs.cc ('K') | « src/debug.cc ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 } 229 }
230 230
231 // Return and remove the on-stack parameters. 231 // Return and remove the on-stack parameters.
232 __ ret(3 * kPointerSize); 232 __ ret(3 * kPointerSize);
233 233
234 __ bind(&slow_case); 234 __ bind(&slow_case);
235 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 235 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
236 } 236 }
237 237
238 238
239 // The stub returns zero for false, and a non-zero value for true. 239 // The stub expects its argument on the stack and returns its result in tos_:
240 // zero for false, and a non-zero value for true.
240 void ToBooleanStub::Generate(MacroAssembler* masm) { 241 void ToBooleanStub::Generate(MacroAssembler* masm) {
241 Label false_result, true_result, not_string; 242 Label patch;
242 Factory* factory = masm->isolate()->factory(); 243 Factory* factory = masm->isolate()->factory();
243 const Register map = edx; 244 const Register map = edx;
244 245
245 __ mov(eax, Operand(esp, 1 * kPointerSize)); 246 if (!types_.IsEmpty()) {
247 __ mov(eax, Operand(esp, 1 * kPointerSize));
248 }
246 249
247 // undefined -> false 250 // undefined -> false
248 __ cmp(eax, factory->undefined_value()); 251 CheckOddball(masm, UNDEFINED, factory->undefined_value(), false, &patch);
249 __ j(equal, &false_result);
250 252
251 // Boolean -> its value 253 // Boolean -> its value
252 __ cmp(eax, factory->false_value()); 254 CheckOddball(masm, BOOLEAN, factory->false_value(), false, &patch);
253 __ j(equal, &false_result); 255 CheckOddball(masm, BOOLEAN, factory->true_value(), true, &patch);
254 __ cmp(eax, factory->true_value());
255 __ j(equal, &true_result);
256
257 // Smis: 0 -> false, all other -> true
258 __ test(eax, Operand(eax));
259 __ j(zero, &false_result);
260 __ JumpIfSmi(eax, &true_result);
261 256
262 // 'null' -> false. 257 // 'null' -> false.
263 __ cmp(eax, factory->null_value()); 258 CheckOddball(masm, NULL_TYPE, factory->null_value(), false, &patch);
264 __ j(equal, &false_result, Label::kNear);
265 259
266 // Get the map of the heap object. 260 bool need_map =
267 __ mov(map, FieldOperand(eax, HeapObject::kMapOffset)); 261 types_.Contains(UNDETECTABLE) |
262 types_.Contains(SPEC_OBJECT) |
263 types_.Contains(STRING) |
264 types_.Contains(HEAP_NUMBER) |
265 types_.Contains(INTERNAL_OBJECT);
268 266
269 // Undetectable -> false. 267 if (types_.Contains(SMI)) {
270 __ test_b(FieldOperand(map, Map::kBitFieldOffset), 268 // Smis: 0 -> false, all other -> true
271 1 << Map::kIsUndetectable); 269 Label not_smi;
272 __ j(not_zero, &false_result, Label::kNear); 270 __ JumpIfNotSmi(eax, &not_smi, Label::kNear);
271 __ ret(1 * kPointerSize); // eax contains the correct value already
272 __ bind(&not_smi);
273 } else if (need_map) {
274 // If we need a map later and have a Smi -> patch.
275 __ JumpIfSmi(eax, &patch, Label::kNear);
276 }
273 277
274 // JavaScript object -> true. 278 if (need_map) {
275 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); 279 __ mov(map, FieldOperand(eax, HeapObject::kMapOffset));
276 __ j(above_equal, &true_result, Label::kNear);
277 280
278 // String value -> false iff empty. 281 // Everything with a map could be undetectable, so check this now.
279 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); 282 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
280 __ j(above_equal, &not_string, Label::kNear); 283 1 << Map::kIsUndetectable);
281 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0)); 284 if (types_.Contains(UNDETECTABLE)) {
282 __ j(zero, &false_result, Label::kNear); 285 // Undetectable -> false.
283 __ jmp(&true_result, Label::kNear); 286 Label not_undetectable;
287 __ j(zero, &not_undetectable, Label::kNear);
288 __ 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. :-)
289 __ ret(1 * kPointerSize);
290 __ bind(&not_undetectable);
291 } else {
292 // We've seen an undetectable value for the first time -> patch.
293 __ j(not_zero, &patch, Label::kNear);
294 }
295 }
284 296
285 __ bind(&not_string); 297 if (types_.Contains(SPEC_OBJECT)) {
286 // HeapNumber -> false iff +0, -0, or NaN. 298 // spec object -> true.
287 __ cmp(map, factory->heap_number_map()); 299 Label not_js_object;
288 __ j(not_equal, &true_result, Label::kNear); 300 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
289 __ fldz(); 301 __ j(below, &not_js_object, Label::kNear);
290 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 302 __ mov(tos_, 1);
291 __ FCmp(); 303 __ ret(1 * kPointerSize);
292 __ j(zero, &false_result, Label::kNear); 304 __ bind(&not_js_object);
293 // Fall through to |true_result|. 305 } else if (types_.Contains(INTERNAL_OBJECT)) {
306 // We've seen a spec object for the first time -> patch.
307 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
308 __ j(above_equal, &patch, Label::kNear);
309 }
294 310
295 // Return 1/0 for true/false in tos_. 311 if (types_.Contains(STRING)) {
296 __ bind(&true_result); 312 // String value -> false iff empty.
297 __ mov(tos_, 1); 313 Label not_string;
298 __ ret(1 * kPointerSize); 314 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
299 __ bind(&false_result); 315 __ j(above_equal, &not_string, Label::kNear);
300 __ mov(tos_, 0); 316 __ 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.
301 __ ret(1 * kPointerSize); 317 __ ret(1 * kPointerSize); // the string length is OK as the return value
318 __ bind(&not_string);
319 } else if (types_.Contains(INTERNAL_OBJECT)) {
320 // We've seen a string for the first time -> patch
321 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
322 __ j(below, &patch, Label::kNear);
323 }
324
325 if (types_.Contains(HEAP_NUMBER)) {
326 // heap number -> false iff +0, -0, or NaN.
327 Label not_heap_number, false_result;
328 __ cmp(map, factory->heap_number_map());
329 __ j(not_equal, &not_heap_number, Label::kNear);
330 __ fldz();
331 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
332 __ FCmp();
333 __ j(zero, &false_result, Label::kNear);
334 __ mov(tos_, 1);
335 __ ret(1 * kPointerSize);
336 __ bind(&false_result);
337 __ xor_(tos_, Operand(tos_));
338 __ ret(1 * kPointerSize);
339 __ bind(&not_heap_number);
340 } else if (types_.Contains(INTERNAL_OBJECT)) {
341 // We've seen a heap number for the first time -> patch
342 __ cmp(map, factory->heap_number_map());
343 __ j(equal, &patch, Label::kNear);
344 }
345
346 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
347 // internal objects -> true
348 __ mov(tos_, 1);
349 __ ret(1 * kPointerSize);
350 }
351
352 __ bind(&patch);
353 GenerateTypeTransition(masm);
354 }
355
356
357 void ToBooleanStub::CheckOddball(MacroAssembler* masm,
358 Type type,
359 Handle<Object> value,
360 bool result,
361 Label* patch) {
362 __ 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.
363 if (types_.Contains(type)) {
364 // If we see an expected oddball, return its ToBoolean value tos_.
365 Label different_value;
366 __ j(not_equal, &different_value, Label::kNear);
367 if (result) {
368 __ mov(tos_, 1);
369 } else {
370 __ xor_(tos_, Operand(tos_));
371 }
372 __ ret(1 * kPointerSize);
373 __ bind(&different_value);
374 } else if (types_.Contains(INTERNAL_OBJECT)) {
375 // If we see an unexpected oddball and handle internal objects, we must
376 // patch because the code for internal objects doesn't handle it explictly.
377 __ j(equal, patch);
378 }
379 }
380
381
382 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
383 __ pop(ecx); // Get return address, operand is now on top of stack.
384 __ push(Immediate(Smi::FromInt(tos_.code())));
385 __ push(Immediate(Smi::FromInt(types_.ToInt())));
386 __ push(ecx); // Push return address.
387 // Patch the caller to an appropriate specialized stub and return the
388 // operation result to the caller of the stub.
389 __ TailCallExternalReference(
390 ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
391 3,
392 1);
302 } 393 }
303 394
304 395
305 class FloatingPointHelper : public AllStatic { 396 class FloatingPointHelper : public AllStatic {
306 public: 397 public:
307 enum ArgLocation { 398 enum ArgLocation {
308 ARGS_ON_STACK, 399 ARGS_ON_STACK,
309 ARGS_IN_REGISTERS 400 ARGS_IN_REGISTERS
310 }; 401 };
311 402
(...skipping 5981 matching lines...) Expand 10 before | Expand all | Expand 10 after
6293 __ Drop(1); 6384 __ Drop(1);
6294 __ ret(2 * kPointerSize); 6385 __ ret(2 * kPointerSize);
6295 } 6386 }
6296 6387
6297 6388
6298 #undef __ 6389 #undef __
6299 6390
6300 } } // namespace v8::internal 6391 } } // namespace v8::internal
6301 6392
6302 #endif // V8_TARGET_ARCH_IA32 6393 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« 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