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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 7544012: Implement type recording for ToBoolean on x64. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 4 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
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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 223 }
224 224
225 // Return and remove the on-stack parameters. 225 // Return and remove the on-stack parameters.
226 __ ret(3 * kPointerSize); 226 __ ret(3 * kPointerSize);
227 227
228 __ bind(&slow_case); 228 __ bind(&slow_case);
229 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 229 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
230 } 230 }
231 231
232 232
233 // The stub returns zero for false, and a non-zero value for true. 233 // The stub expects its argument on the stack and returns its result in tos_:
234 // zero for false, and a non-zero value for true.
234 void ToBooleanStub::Generate(MacroAssembler* masm) { 235 void ToBooleanStub::Generate(MacroAssembler* masm) {
235 Label false_result, true_result, not_string; 236 Label patch;
237 const Register argument = rax;
236 const Register map = rdx; 238 const Register map = rdx;
237 239
238 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 240 if (!types_.IsEmpty()) {
241 __ movq(argument, Operand(rsp, 1 * kPointerSize));
242 }
239 243
240 // undefined -> false 244 // undefined -> false
241 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 245 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false, &patch);
242 __ j(equal, &false_result);
243 246
244 // Boolean -> its value 247 // Boolean -> its value
245 __ CompareRoot(rax, Heap::kFalseValueRootIndex); 248 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false, &patch);
246 __ j(equal, &false_result); 249 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true, &patch);
247 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
248 __ j(equal, &true_result);
249
250 // Smis: 0 -> false, all other -> true
251 __ Cmp(rax, Smi::FromInt(0));
252 __ j(equal, &false_result);
253 __ JumpIfSmi(rax, &true_result);
254 250
255 // 'null' -> false. 251 // 'null' -> false.
256 __ CompareRoot(rax, Heap::kNullValueRootIndex); 252 CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false, &patch);
257 __ j(equal, &false_result, Label::kNear);
258 253
259 // Get the map of the heap object. 254 if (types_.Contains(SMI)) {
260 __ movq(map, FieldOperand(rax, HeapObject::kMapOffset)); 255 // Smis: 0 -> false, all other -> true
256 Label not_smi;
257 __ JumpIfNotSmi(argument, &not_smi, Label::kNear);
258 // argument contains the correct return value already
259 if (!tos_.is(argument)) {
260 __ movq(tos_, argument);
261 }
262 __ ret(1 * kPointerSize);
263 __ bind(&not_smi);
264 } else if (types_.NeedsMap()) {
265 // If we need a map later and have a Smi -> patch.
266 __ JumpIfSmi(argument, &patch, Label::kNear);
267 }
261 268
262 // Undetectable -> false. 269 if (types_.NeedsMap()) {
263 __ testb(FieldOperand(map, Map::kBitFieldOffset), 270 __ movq(map, FieldOperand(argument, HeapObject::kMapOffset));
264 Immediate(1 << Map::kIsUndetectable));
265 __ j(not_zero, &false_result, Label::kNear);
266 271
267 // JavaScript object -> true. 272 // Everything with a map could be undetectable, so check this now.
268 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); 273 __ testb(FieldOperand(map, Map::kBitFieldOffset),
269 __ j(above_equal, &true_result, Label::kNear); 274 Immediate(1 << Map::kIsUndetectable));
275 // Undetectable -> false.
276 Label not_undetectable;
277 __ j(zero, &not_undetectable, Label::kNear);
278 __ Set(tos_, 0);
279 __ ret(1 * kPointerSize);
280 __ bind(&not_undetectable);
281 }
270 282
271 // String value -> false iff empty. 283 if (types_.Contains(SPEC_OBJECT)) {
272 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); 284 // spec object -> true.
273 __ j(above_equal, &not_string, Label::kNear); 285 Label not_js_object;
274 __ cmpq(FieldOperand(rax, String::kLengthOffset), Immediate(0)); 286 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
275 __ j(zero, &false_result, Label::kNear); 287 __ j(below, &not_js_object, Label::kNear);
276 __ jmp(&true_result, Label::kNear); 288 __ Set(tos_, 1);
289 __ ret(1 * kPointerSize);
290 __ bind(&not_js_object);
291 } else if (types_.Contains(INTERNAL_OBJECT)) {
292 // We've seen a spec object for the first time -> patch.
293 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
294 __ j(above_equal, &patch, Label::kNear);
295 }
277 296
278 __ bind(&not_string); 297 if (types_.Contains(STRING)) {
279 // HeapNumber -> false iff +0, -0, or NaN. 298 // String value -> false iff empty.
280 // These three cases set the zero flag when compared to zero using ucomisd. 299 Label not_string;
281 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); 300 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
282 __ j(not_equal, &true_result, Label::kNear); 301 __ j(above_equal, &not_string, Label::kNear);
283 __ xorps(xmm0, xmm0); 302 __ movq(tos_, FieldOperand(argument, String::kLengthOffset));
284 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); 303 __ ret(1 * kPointerSize); // the string length is OK as the return value
285 __ j(zero, &false_result, Label::kNear); 304 __ bind(&not_string);
286 // Fall through to |true_result|. 305 } else if (types_.Contains(INTERNAL_OBJECT)) {
306 // We've seen a string for the first time -> patch
307 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
308 __ j(below, &patch, Label::kNear);
309 }
287 310
288 // Return 1/0 for true/false in tos_. 311 if (types_.Contains(HEAP_NUMBER)) {
289 __ bind(&true_result); 312 // heap number -> false iff +0, -0, or NaN.
290 __ Set(tos_, 1); 313 Label not_heap_number, false_result;
291 __ ret(1 * kPointerSize); 314 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
292 __ bind(&false_result); 315 __ j(not_equal, &not_heap_number, Label::kNear);
293 __ Set(tos_, 0); 316 __ xorps(xmm0, xmm0);
294 __ ret(1 * kPointerSize); 317 __ ucomisd(xmm0, FieldOperand(argument, HeapNumber::kValueOffset));
318 __ j(zero, &false_result, Label::kNear);
319 __ Set(tos_, 1);
320 __ ret(1 * kPointerSize);
321 __ bind(&false_result);
322 __ Set(tos_, 0);
323 __ ret(1 * kPointerSize);
324 __ bind(&not_heap_number);
325 } else if (types_.Contains(INTERNAL_OBJECT)) {
326 // We've seen a heap number for the first time -> patch
327 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
328 __ j(equal, &patch, Label::kNear);
329 }
330
331 if (types_.Contains(INTERNAL_OBJECT)) {
332 // internal objects -> true
333 __ Set(tos_, 1);
334 __ ret(1 * kPointerSize);
335 }
336
337 if (!types_.IsAll()) {
338 __ bind(&patch);
339 GenerateTypeTransition(masm);
340 }
341 }
342
343
344 void ToBooleanStub::CheckOddball(MacroAssembler* masm,
345 Type type,
346 Heap::RootListIndex value,
347 bool result,
348 Label* patch) {
349 const Register argument = rax;
350 if (types_.Contains(type)) {
351 // If we see an expected oddball, return its ToBoolean value tos_.
352 Label different_value;
353 __ CompareRoot(argument, value);
354 __ j(not_equal, &different_value, Label::kNear);
355 __ Set(tos_, result ? 1 : 0);
356 __ ret(1 * kPointerSize);
357 __ bind(&different_value);
358 } else if (types_.Contains(INTERNAL_OBJECT)) {
359 // If we see an unexpected oddball and handle internal objects, we must
360 // patch because the code for internal objects doesn't handle it explictly.
361 __ CompareRoot(argument, value);
362 __ j(equal, patch);
363 }
364 }
365
366
367 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
368 __ pop(rcx); // Get return address, operand is now on top of stack.
369 __ Push(Smi::FromInt(tos_.code()));
370 __ Push(Smi::FromInt(types_.ToByte()));
371 __ push(rcx); // Push return address.
372 // Patch the caller to an appropriate specialized stub and return the
373 // operation result to the caller of the stub.
374 __ TailCallExternalReference(
375 ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
376 3,
377 1);
295 } 378 }
296 379
297 380
298 class FloatingPointHelper : public AllStatic { 381 class FloatingPointHelper : public AllStatic {
299 public: 382 public:
300 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. 383 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles.
301 // If the operands are not both numbers, jump to not_numbers. 384 // If the operands are not both numbers, jump to not_numbers.
302 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. 385 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis.
303 // NumberOperands assumes both are smis or heap numbers. 386 // NumberOperands assumes both are smis or heap numbers.
304 static void LoadSSE2SmiOperands(MacroAssembler* masm); 387 static void LoadSSE2SmiOperands(MacroAssembler* masm);
(...skipping 4978 matching lines...) Expand 10 before | Expand all | Expand 10 after
5283 __ Drop(1); 5366 __ Drop(1);
5284 __ ret(2 * kPointerSize); 5367 __ ret(2 * kPointerSize);
5285 } 5368 }
5286 5369
5287 5370
5288 #undef __ 5371 #undef __
5289 5372
5290 } } // namespace v8::internal 5373 } } // namespace v8::internal
5291 5374
5292 #endif // V8_TARGET_ARCH_X64 5375 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698