| 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 |