OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 switch (location_) { | 207 switch (location_) { |
208 case kAccumulator: | 208 case kAccumulator: |
209 if (!reg.is(result_register())) __ mov(result_register(), reg); | 209 if (!reg.is(result_register())) __ mov(result_register(), reg); |
210 break; | 210 break; |
211 case kStack: | 211 case kStack: |
212 __ push(reg); | 212 __ push(reg); |
213 break; | 213 break; |
214 } | 214 } |
215 break; | 215 break; |
216 | 216 |
217 case Expression::kValueTest: | |
218 case Expression::kTestValue: | |
219 // Push an extra copy of the value in case it's needed. | |
220 __ push(reg); | |
221 // Fall through. | |
222 | |
223 case Expression::kTest: | 217 case Expression::kTest: |
224 // For simplicity we always test the accumulator register. | 218 // For simplicity we always test the accumulator register. |
225 if (!reg.is(result_register())) __ mov(result_register(), reg); | 219 if (!reg.is(result_register())) __ mov(result_register(), reg); |
226 DoTest(context); | 220 DoTest(context); |
227 break; | 221 break; |
| 222 |
| 223 case Expression::kValueTest: |
| 224 case Expression::kTestValue: |
| 225 if (!reg.is(result_register())) __ mov(result_register(), reg); |
| 226 switch (location_) { |
| 227 case kAccumulator: |
| 228 break; |
| 229 case kStack: |
| 230 __ push(result_register()); |
| 231 break; |
| 232 } |
| 233 DoTest(context); |
| 234 break; |
228 } | 235 } |
229 } | 236 } |
230 | 237 |
231 | 238 |
232 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 239 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
233 switch (context) { | 240 switch (context) { |
234 case Expression::kUninitialized: | 241 case Expression::kUninitialized: |
235 UNREACHABLE(); | 242 UNREACHABLE(); |
236 case Expression::kEffect: | 243 case Expression::kEffect: |
237 // Nothing to do. | 244 // Nothing to do. |
238 break; | 245 break; |
239 case Expression::kValue: { | 246 case Expression::kValue: { |
240 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); | 247 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); |
241 switch (location_) { | 248 switch (location_) { |
242 case kAccumulator: | 249 case kAccumulator: |
243 __ mov(result_register(), slot_operand); | 250 __ mov(result_register(), slot_operand); |
244 break; | 251 break; |
245 case kStack: | 252 case kStack: |
246 // Memory operands can be pushed directly. | 253 // Memory operands can be pushed directly. |
247 __ push(slot_operand); | 254 __ push(slot_operand); |
248 break; | 255 break; |
249 } | 256 } |
250 break; | 257 break; |
251 } | 258 } |
252 | 259 |
253 case Expression::kTest: | 260 case Expression::kTest: |
| 261 // For simplicity we always test the accumulator register. |
254 Move(result_register(), slot); | 262 Move(result_register(), slot); |
255 DoTest(context); | 263 DoTest(context); |
256 break; | 264 break; |
257 | 265 |
258 case Expression::kValueTest: | 266 case Expression::kValueTest: |
259 case Expression::kTestValue: | 267 case Expression::kTestValue: |
260 Move(result_register(), slot); | 268 Move(result_register(), slot); |
261 __ push(result_register()); | 269 switch (location_) { |
| 270 case kAccumulator: |
| 271 break; |
| 272 case kStack: |
| 273 __ push(result_register()); |
| 274 break; |
| 275 } |
262 DoTest(context); | 276 DoTest(context); |
263 break; | 277 break; |
264 } | 278 } |
265 } | 279 } |
266 | 280 |
267 | 281 |
268 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 282 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
269 switch (context) { | 283 switch (context) { |
270 case Expression::kUninitialized: | 284 case Expression::kUninitialized: |
271 UNREACHABLE(); | 285 UNREACHABLE(); |
272 case Expression::kEffect: | 286 case Expression::kEffect: |
273 // Nothing to do. | 287 // Nothing to do. |
274 break; | 288 break; |
275 case Expression::kValue: | 289 case Expression::kValue: |
276 switch (location_) { | 290 switch (location_) { |
277 case kAccumulator: | 291 case kAccumulator: |
278 __ mov(result_register(), lit->handle()); | 292 __ mov(result_register(), lit->handle()); |
279 break; | 293 break; |
280 case kStack: | 294 case kStack: |
281 // Immediates can be pushed directly. | 295 // Immediates can be pushed directly. |
282 __ push(Immediate(lit->handle())); | 296 __ push(Immediate(lit->handle())); |
283 break; | 297 break; |
284 } | 298 } |
285 break; | 299 break; |
286 | 300 |
287 case Expression::kTest: | 301 case Expression::kTest: |
| 302 // For simplicity we always test the accumulator register. |
288 __ mov(result_register(), lit->handle()); | 303 __ mov(result_register(), lit->handle()); |
289 DoTest(context); | 304 DoTest(context); |
290 break; | 305 break; |
291 | 306 |
292 case Expression::kValueTest: | 307 case Expression::kValueTest: |
293 case Expression::kTestValue: | 308 case Expression::kTestValue: |
294 __ mov(result_register(), lit->handle()); | 309 __ mov(result_register(), lit->handle()); |
295 __ push(result_register()); | 310 switch (location_) { |
| 311 case kAccumulator: |
| 312 break; |
| 313 case kStack: |
| 314 __ push(result_register()); |
| 315 break; |
| 316 } |
296 DoTest(context); | 317 DoTest(context); |
297 break; | 318 break; |
298 } | 319 } |
299 } | 320 } |
300 | 321 |
301 | 322 |
302 void FastCodeGenerator::ApplyTOS(Expression::Context context) { | 323 void FastCodeGenerator::ApplyTOS(Expression::Context context) { |
303 switch (context) { | 324 switch (context) { |
304 case Expression::kUninitialized: | 325 case Expression::kUninitialized: |
305 UNREACHABLE(); | 326 UNREACHABLE(); |
306 | 327 |
307 case Expression::kEffect: | 328 case Expression::kEffect: |
308 __ Drop(1); | 329 __ Drop(1); |
309 break; | 330 break; |
310 | 331 |
311 case Expression::kValue: | 332 case Expression::kValue: |
312 switch (location_) { | 333 switch (location_) { |
313 case kAccumulator: | 334 case kAccumulator: |
314 __ pop(result_register()); | 335 __ pop(result_register()); |
315 break; | 336 break; |
316 case kStack: | 337 case kStack: |
317 break; | 338 break; |
318 } | 339 } |
319 break; | 340 break; |
320 | 341 |
321 case Expression::kTest: | 342 case Expression::kTest: |
| 343 // For simplicity we always test the accumulator register. |
322 __ pop(result_register()); | 344 __ pop(result_register()); |
323 DoTest(context); | 345 DoTest(context); |
324 break; | 346 break; |
325 | 347 |
326 case Expression::kValueTest: | 348 case Expression::kValueTest: |
327 case Expression::kTestValue: | 349 case Expression::kTestValue: |
328 __ mov(result_register(), Operand(esp, 0)); | 350 switch (location_) { |
| 351 case kAccumulator: |
| 352 __ pop(result_register()); |
| 353 break; |
| 354 case kStack: |
| 355 __ mov(result_register(), Operand(esp, 0)); |
| 356 break; |
| 357 } |
329 DoTest(context); | 358 DoTest(context); |
330 break; | 359 break; |
331 } | 360 } |
332 } | 361 } |
333 | 362 |
334 | 363 |
335 void FastCodeGenerator::DropAndApply(int count, | 364 void FastCodeGenerator::DropAndApply(int count, |
336 Expression::Context context, | 365 Expression::Context context, |
337 Register reg) { | 366 Register reg) { |
338 ASSERT(count > 0); | 367 ASSERT(count > 0); |
(...skipping 13 matching lines...) Expand all Loading... |
352 if (!reg.is(result_register())) __ mov(result_register(), reg); | 381 if (!reg.is(result_register())) __ mov(result_register(), reg); |
353 break; | 382 break; |
354 case kStack: | 383 case kStack: |
355 if (count > 1) __ Drop(count - 1); | 384 if (count > 1) __ Drop(count - 1); |
356 __ mov(Operand(esp, 0), reg); | 385 __ mov(Operand(esp, 0), reg); |
357 break; | 386 break; |
358 } | 387 } |
359 break; | 388 break; |
360 | 389 |
361 case Expression::kTest: | 390 case Expression::kTest: |
| 391 // For simplicity we always test the accumulator register. |
362 __ Drop(count); | 392 __ Drop(count); |
363 if (!reg.is(result_register())) __ mov(result_register(), reg); | 393 if (!reg.is(result_register())) __ mov(result_register(), reg); |
364 DoTest(context); | 394 DoTest(context); |
365 break; | 395 break; |
366 | 396 |
367 case Expression::kValueTest: | 397 case Expression::kValueTest: |
368 case Expression::kTestValue: | 398 case Expression::kTestValue: |
369 if (count > 1) __ Drop(count - 1); | 399 switch (location_) { |
370 if (!reg.is(result_register())) __ mov(result_register(), reg); | 400 case kAccumulator: |
371 __ mov(Operand(esp, 0), result_register()); | 401 __ Drop(count); |
| 402 if (!reg.is(result_register())) __ mov(result_register(), reg); |
| 403 break; |
| 404 case kStack: |
| 405 if (count > 1) __ Drop(count - 1); |
| 406 __ mov(result_register(), reg); |
| 407 __ mov(Operand(esp, 0), result_register()); |
| 408 break; |
| 409 } |
372 DoTest(context); | 410 DoTest(context); |
373 break; | 411 break; |
374 } | 412 } |
375 } | 413 } |
376 | 414 |
377 | 415 |
378 void FastCodeGenerator::Apply(Expression::Context context, | 416 void FastCodeGenerator::Apply(Expression::Context context, |
379 Label* materialize_true, | 417 Label* materialize_true, |
380 Label* materialize_false) { | 418 Label* materialize_false) { |
381 switch (context) { | 419 switch (context) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 __ push(Immediate(Factory::false_value())); | 471 __ push(Immediate(Factory::false_value())); |
434 break; | 472 break; |
435 } | 473 } |
436 __ jmp(false_label_); | 474 __ jmp(false_label_); |
437 break; | 475 break; |
438 } | 476 } |
439 } | 477 } |
440 | 478 |
441 | 479 |
442 void FastCodeGenerator::DoTest(Expression::Context context) { | 480 void FastCodeGenerator::DoTest(Expression::Context context) { |
443 // The value to test is in the accumulator, and duplicated on the stack if | 481 // The value to test is in the accumulator. If the value might be needed |
444 // necessary (for value/test and test/value contexts). | 482 // on the stack (value/test and test/value contexts with a stack location |
| 483 // desired), then the value is already duplicated on the stack. |
445 ASSERT_NE(NULL, true_label_); | 484 ASSERT_NE(NULL, true_label_); |
446 ASSERT_NE(NULL, false_label_); | 485 ASSERT_NE(NULL, false_label_); |
447 | 486 |
448 // If there is a value on the stack, use a discard label for the | 487 // In value/test and test/value expression contexts with stack as the |
449 // value-is-unneeded branch in the inlined part of the test. | 488 // desired location, there is already an extra value on the stack. Use a |
| 489 // label to discard it if unneeded. |
450 Label discard; | 490 Label discard; |
451 Label* if_true = | 491 Label* if_true = true_label_; |
452 (context == Expression::kTestValue) ? &discard : true_label_; | 492 Label* if_false = false_label_; |
453 Label* if_false = | 493 switch (context) { |
454 (context == Expression::kValueTest) ? &discard : false_label_; | 494 case Expression::kUninitialized: |
| 495 case Expression::kEffect: |
| 496 case Expression::kValue: |
| 497 UNREACHABLE(); |
| 498 case Expression::kTest: |
| 499 break; |
| 500 case Expression::kValueTest: |
| 501 switch (location_) { |
| 502 case kAccumulator: |
| 503 break; |
| 504 case kStack: |
| 505 if_false = &discard; |
| 506 break; |
| 507 } |
| 508 break; |
| 509 case Expression::kTestValue: |
| 510 switch (location_) { |
| 511 case kAccumulator: |
| 512 break; |
| 513 case kStack: |
| 514 if_true = &discard; |
| 515 break; |
| 516 } |
| 517 break; |
| 518 } |
455 | 519 |
456 // Emit the inlined tests assumed by the stub. | 520 // Emit the inlined tests assumed by the stub. |
457 __ cmp(result_register(), Factory::undefined_value()); | 521 __ cmp(result_register(), Factory::undefined_value()); |
458 __ j(equal, if_false); | 522 __ j(equal, if_false); |
459 __ cmp(result_register(), Factory::true_value()); | 523 __ cmp(result_register(), Factory::true_value()); |
460 __ j(equal, if_true); | 524 __ j(equal, if_true); |
461 __ cmp(result_register(), Factory::false_value()); | 525 __ cmp(result_register(), Factory::false_value()); |
462 __ j(equal, if_false); | 526 __ j(equal, if_false); |
463 ASSERT_EQ(0, kSmiTag); | 527 ASSERT_EQ(0, kSmiTag); |
464 __ test(result_register(), Operand(result_register())); | 528 __ test(result_register(), Operand(result_register())); |
465 __ j(zero, if_false); | 529 __ j(zero, if_false); |
466 __ test(result_register(), Immediate(kSmiTagMask)); | 530 __ test(result_register(), Immediate(kSmiTagMask)); |
467 __ j(zero, if_true); | 531 __ j(zero, if_true); |
468 | 532 |
| 533 // Save a copy of the value if it may be needed and isn't already saved. |
| 534 switch (context) { |
| 535 case Expression::kUninitialized: |
| 536 case Expression::kEffect: |
| 537 case Expression::kValue: |
| 538 UNREACHABLE(); |
| 539 case Expression::kTest: |
| 540 break; |
| 541 case Expression::kValueTest: |
| 542 switch (location_) { |
| 543 case kAccumulator: |
| 544 __ push(result_register()); |
| 545 break; |
| 546 case kStack: |
| 547 break; |
| 548 } |
| 549 break; |
| 550 case Expression::kTestValue: |
| 551 switch (location_) { |
| 552 case kAccumulator: |
| 553 __ push(result_register()); |
| 554 break; |
| 555 case kStack: |
| 556 break; |
| 557 } |
| 558 break; |
| 559 } |
| 560 |
469 // Call the ToBoolean stub for all other cases. | 561 // Call the ToBoolean stub for all other cases. |
470 ToBooleanStub stub; | 562 ToBooleanStub stub; |
471 __ push(result_register()); | 563 __ push(result_register()); |
472 __ CallStub(&stub); | 564 __ CallStub(&stub); |
473 __ test(eax, Operand(eax)); | 565 __ test(eax, Operand(eax)); |
474 | 566 |
475 // The stub returns nonzero for true. Complete based on the context. | 567 // The stub returns nonzero for true. Complete based on the context. |
476 switch (context) { | 568 switch (context) { |
477 case Expression::kUninitialized: | 569 case Expression::kUninitialized: |
478 case Expression::kEffect: | 570 case Expression::kEffect: |
(...skipping 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1711 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 1803 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
1712 __ mov(Operand(esp, 0), edx); | 1804 __ mov(Operand(esp, 0), edx); |
1713 // And return. | 1805 // And return. |
1714 __ ret(0); | 1806 __ ret(0); |
1715 } | 1807 } |
1716 | 1808 |
1717 | 1809 |
1718 #undef __ | 1810 #undef __ |
1719 | 1811 |
1720 } } // namespace v8::internal | 1812 } } // namespace v8::internal |
OLD | NEW |