Chromium Code Reviews| 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 18 matching lines...) Expand all Loading... | |
| 29 | 29 |
| 30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
| 31 #include "compiler.h" | 31 #include "compiler.h" |
| 32 #include "fast-codegen.h" | 32 #include "fast-codegen.h" |
| 33 #include "stub-cache.h" | 33 #include "stub-cache.h" |
| 34 #include "debug.h" | 34 #include "debug.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 #define __ ACCESS_MASM(masm_) | 39 #define __ ACCESS_MASM(masm()) |
| 40 | 40 |
| 41 Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun, | 41 Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun, |
| 42 Handle<Script> script, | 42 Handle<Script> script, |
| 43 bool is_eval) { | 43 bool is_eval) { |
| 44 CodeGenerator::MakeCodePrologue(fun); | 44 CodeGenerator::MakeCodePrologue(fun); |
| 45 const int kInitialBufferSize = 4 * KB; | 45 const int kInitialBufferSize = 4 * KB; |
| 46 MacroAssembler masm(NULL, kInitialBufferSize); | 46 MacroAssembler masm(NULL, kInitialBufferSize); |
| 47 FastCodeGenerator cgen(&masm, script, is_eval); | 47 FastCodeGenerator cgen(&masm, script, is_eval); |
| 48 cgen.Generate(fun); | 48 cgen.Generate(fun); |
| 49 if (cgen.HasStackOverflow()) { | 49 if (cgen.HasStackOverflow()) { |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 | 225 |
| 226 __ bind(&eval_right); | 226 __ bind(&eval_right); |
| 227 Visit(expr->right()); | 227 Visit(expr->right()); |
| 228 | 228 |
| 229 __ bind(&done); | 229 __ bind(&done); |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 void FastCodeGenerator::VisitBlock(Block* stmt) { | 233 void FastCodeGenerator::VisitBlock(Block* stmt) { |
| 234 Comment cmnt(masm_, "[ Block"); | 234 Comment cmnt(masm_, "[ Block"); |
| 235 Label end_of_block; | |
| 236 Breakable nested_statement(this, stmt, &end_of_block); | |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
If the label is part of the state of the Breakable
| |
| 235 SetStatementPosition(stmt); | 237 SetStatementPosition(stmt); |
| 236 VisitStatements(stmt->statements()); | 238 VisitStatements(stmt->statements()); |
| 239 __ bind(&end_of_block); | |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
And
__ bind(nested_statement.break_target());
| |
| 237 } | 240 } |
| 238 | 241 |
| 239 | 242 |
| 240 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 243 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 241 Comment cmnt(masm_, "[ ExpressionStatement"); | 244 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 242 SetStatementPosition(stmt); | 245 SetStatementPosition(stmt); |
| 243 Visit(stmt->expression()); | 246 Visit(stmt->expression()); |
| 244 } | 247 } |
| 245 | 248 |
| 246 | 249 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 271 __ jmp(&done); | 274 __ jmp(&done); |
| 272 | 275 |
| 273 __ bind(&else_part); | 276 __ bind(&else_part); |
| 274 Visit(stmt->else_statement()); | 277 Visit(stmt->else_statement()); |
| 275 | 278 |
| 276 __ bind(&done); | 279 __ bind(&done); |
| 277 } | 280 } |
| 278 | 281 |
| 279 | 282 |
| 280 void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 283 void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
| 281 UNREACHABLE(); | 284 NestedStatement* current = nesting_stack_; |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
Might be nice to have a codegen comment "[ Continu
Lasse Reichstein
2009/12/10 13:55:32
Fixed
| |
| 285 int stack_depth = 0; | |
| 286 while (!current->IsContinueTarget(stmt->target())) { | |
| 287 stack_depth = current->Exit(stack_depth); | |
| 288 current = current->outer(); | |
| 289 } | |
| 290 __ Drop(stack_depth); | |
| 291 | |
| 292 Iteration* loop = current->AsIteration(); | |
| 293 __ jmp(loop->continue_target()); | |
| 282 } | 294 } |
| 283 | 295 |
| 284 | 296 |
| 285 void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 297 void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 286 UNREACHABLE(); | 298 NestedStatement* current = nesting_stack_; |
| 299 int stack_depth = 0; | |
| 300 while (!current->IsBreakTarget(stmt->target())) { | |
| 301 stack_depth = current->Exit(stack_depth); | |
| 302 current = current->outer(); | |
| 303 } | |
| 304 __ Drop(stack_depth); | |
| 305 | |
| 306 Breakable* target = current->AsBreakable(); | |
| 307 __ jmp(target->break_target()); | |
| 287 } | 308 } |
| 288 | 309 |
| 289 | 310 |
| 311 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | |
| 312 Comment cmnt(masm_, "[ ReturnStatement"); | |
| 313 Expression* expr = stmt->expression(); | |
| 314 // Complete the statement based on the type of the subexpression. | |
| 315 if (expr->AsLiteral() != NULL) { | |
| 316 __ Move(result_register(), expr->AsLiteral()->handle()); | |
| 317 } else { | |
| 318 ASSERT_EQ(Expression::kValue, expr->context()); | |
| 319 Visit(expr); | |
| 320 __ pop(result_register()); | |
| 321 } | |
| 322 | |
| 323 // Exit all nested statements. | |
| 324 NestedStatement* current = nesting_stack_; | |
| 325 int stack_depth = 0; | |
| 326 while (current != NULL) { | |
| 327 stack_depth = current->Exit(stack_depth); | |
| 328 current = current->outer(); | |
| 329 } | |
| 330 __ Drop(stack_depth); | |
| 331 | |
| 332 EmitReturnSequence(stmt->statement_pos()); | |
| 333 } | |
| 334 | |
| 335 | |
| 336 | |
| 337 | |
| 290 void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { | 338 void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { |
| 291 UNREACHABLE(); | 339 UNREACHABLE(); |
| 292 } | 340 } |
| 293 | 341 |
| 294 | 342 |
| 295 void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { | 343 void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { |
| 296 UNREACHABLE(); | 344 UNREACHABLE(); |
| 297 } | 345 } |
| 298 | 346 |
| 299 | 347 |
| 300 void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 348 void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 301 UNREACHABLE(); | 349 UNREACHABLE(); |
| 302 } | 350 } |
| 303 | 351 |
| 304 | 352 |
| 305 void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 353 void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 306 Comment cmnt(masm_, "[ DoWhileStatement"); | 354 Comment cmnt(masm_, "[ DoWhileStatement"); |
| 355 Label body, test, exit, stack_limit_hit, stack_check_success; | |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
exit and test could be fields of the Iteration.
| |
| 356 | |
| 307 increment_loop_depth(); | 357 increment_loop_depth(); |
|
Kevin Millikin (Chromium)
2009/12/10 13:28:28
Another comment: it seems nicer to properly nest t
Lasse Reichstein
2009/12/10 13:55:32
Fixed
| |
| 308 Label body, exit, stack_limit_hit, stack_check_success; | |
| 309 | 358 |
| 310 __ bind(&body); | 359 __ bind(&body); |
| 360 Iteration loop_statement(this, stmt, &exit, &test); | |
| 311 Visit(stmt->body()); | 361 Visit(stmt->body()); |
| 312 | 362 |
| 313 // Check stack before looping. | 363 // Check stack before looping. |
| 314 __ StackLimitCheck(&stack_limit_hit); | 364 __ StackLimitCheck(&stack_limit_hit); |
| 315 __ bind(&stack_check_success); | 365 __ bind(&stack_check_success); |
| 316 | 366 |
| 317 // We are not in an expression context because we have been compiling | 367 // We are not in an expression context because we have been compiling |
| 318 // statements. Set up a test expression context for the condition. | 368 // statements. Set up a test expression context for the condition. |
| 369 __ bind(&test); | |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
__ bind(loop_statement.continue_target());
| |
| 319 ASSERT_EQ(NULL, true_label_); | 370 ASSERT_EQ(NULL, true_label_); |
| 320 ASSERT_EQ(NULL, false_label_); | 371 ASSERT_EQ(NULL, false_label_); |
| 321 true_label_ = &body; | 372 true_label_ = &body; |
| 322 false_label_ = &exit; | 373 false_label_ = &exit; |
| 323 ASSERT(stmt->cond()->context() == Expression::kTest); | 374 ASSERT(stmt->cond()->context() == Expression::kTest); |
| 324 Visit(stmt->cond()); | 375 Visit(stmt->cond()); |
| 325 true_label_ = NULL; | 376 true_label_ = NULL; |
| 326 false_label_ = NULL; | 377 false_label_ = NULL; |
| 327 | 378 |
| 328 __ bind(&stack_limit_hit); | 379 __ bind(&stack_limit_hit); |
| 329 StackCheckStub stack_stub; | 380 StackCheckStub stack_stub; |
| 330 __ CallStub(&stack_stub); | 381 __ CallStub(&stack_stub); |
| 331 __ jmp(&stack_check_success); | 382 __ jmp(&stack_check_success); |
| 332 | 383 |
| 333 __ bind(&exit); | 384 __ bind(&exit); |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
__ bind(loop_statement.break_target());
| |
| 334 | 385 |
| 335 decrement_loop_depth(); | 386 decrement_loop_depth(); |
| 336 } | 387 } |
| 337 | 388 |
| 338 | 389 |
| 339 void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 390 void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| 340 Comment cmnt(masm_, "[ WhileStatement"); | 391 Comment cmnt(masm_, "[ WhileStatement"); |
| 392 Label test, body, exit, stack_limit_hit, stack_check_success; | |
| 393 | |
| 341 increment_loop_depth(); | 394 increment_loop_depth(); |
| 342 Label test, body, exit, stack_limit_hit, stack_check_success; | |
| 343 | 395 |
| 344 // Emit the test at the bottom of the loop. | 396 // Emit the test at the bottom of the loop. |
| 345 __ jmp(&test); | 397 __ jmp(&test); |
| 346 | 398 |
| 347 __ bind(&body); | 399 __ bind(&body); |
| 400 Iteration loop_stamt(this, stmt, &exit, &test); | |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
loop_statement? loop_stmt?
Lasse Reichstein
2009/12/10 13:55:32
Odd typo. Fixed.
| |
| 348 Visit(stmt->body()); | 401 Visit(stmt->body()); |
| 349 | 402 |
| 350 __ bind(&test); | 403 __ bind(&test); |
| 351 // Check stack before looping. | 404 // Check stack before looping. |
| 352 __ StackLimitCheck(&stack_limit_hit); | 405 __ StackLimitCheck(&stack_limit_hit); |
| 353 __ bind(&stack_check_success); | 406 __ bind(&stack_check_success); |
| 354 | 407 |
| 355 // We are not in an expression context because we have been compiling | 408 // We are not in an expression context because we have been compiling |
| 356 // statements. Set up a test expression context for the condition. | 409 // statements. Set up a test expression context for the condition. |
| 357 ASSERT_EQ(NULL, true_label_); | 410 ASSERT_EQ(NULL, true_label_); |
| 358 ASSERT_EQ(NULL, false_label_); | 411 ASSERT_EQ(NULL, false_label_); |
| 359 true_label_ = &body; | 412 true_label_ = &body; |
| 360 false_label_ = &exit; | 413 false_label_ = &exit; |
| 361 ASSERT(stmt->cond()->context() == Expression::kTest); | 414 ASSERT(stmt->cond()->context() == Expression::kTest); |
| 362 Visit(stmt->cond()); | 415 Visit(stmt->cond()); |
| 363 true_label_ = NULL; | 416 true_label_ = NULL; |
| 364 false_label_ = NULL; | 417 false_label_ = NULL; |
| 365 | 418 |
| 366 __ bind(&stack_limit_hit); | 419 __ bind(&stack_limit_hit); |
| 367 StackCheckStub stack_stub; | 420 StackCheckStub stack_stub; |
| 368 __ CallStub(&stack_stub); | 421 __ CallStub(&stack_stub); |
| 369 __ jmp(&stack_check_success); | 422 __ jmp(&stack_check_success); |
| 370 | 423 |
| 371 __ bind(&exit); | 424 __ bind(&exit); |
| 372 | |
| 373 decrement_loop_depth(); | 425 decrement_loop_depth(); |
| 374 } | 426 } |
| 375 | 427 |
| 376 | 428 |
| 377 void FastCodeGenerator::VisitForStatement(ForStatement* stmt) { | 429 void FastCodeGenerator::VisitForStatement(ForStatement* stmt) { |
| 378 Comment cmnt(masm_, "[ ForStatement"); | 430 Comment cmnt(masm_, "[ ForStatement"); |
| 379 Label test, body, exit, stack_limit_hit, stack_check_success; | 431 Label test, body, next, exit, stack_limit_hit, stack_check_success; |
| 380 if (stmt->init() != NULL) Visit(stmt->init()); | 432 if (stmt->init() != NULL) Visit(stmt->init()); |
| 381 | 433 |
| 382 increment_loop_depth(); | 434 increment_loop_depth(); |
| 435 | |
| 383 // Emit the test at the bottom of the loop (even if empty). | 436 // Emit the test at the bottom of the loop (even if empty). |
| 384 __ jmp(&test); | 437 __ jmp(&test); |
| 438 | |
| 385 __ bind(&body); | 439 __ bind(&body); |
| 440 Iteration loop_stamt(this, stmt, &exit, &next); | |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
loop_statement?
| |
| 386 Visit(stmt->body()); | 441 Visit(stmt->body()); |
| 387 | 442 |
| 388 // Check stack before looping. | 443 // Check stack before looping. |
| 389 __ StackLimitCheck(&stack_limit_hit); | 444 __ StackLimitCheck(&stack_limit_hit); |
| 390 __ bind(&stack_check_success); | 445 __ bind(&stack_check_success); |
| 391 | 446 |
| 447 __ bind(&next); | |
| 448 | |
| 392 if (stmt->next() != NULL) Visit(stmt->next()); | 449 if (stmt->next() != NULL) Visit(stmt->next()); |
| 393 | 450 |
| 394 __ bind(&test); | 451 __ bind(&test); |
| 395 | 452 |
| 396 if (stmt->cond() == NULL) { | 453 if (stmt->cond() == NULL) { |
| 397 // For an empty test jump to the top of the loop. | 454 // For an empty test jump to the top of the loop. |
| 398 __ jmp(&body); | 455 __ jmp(&body); |
| 399 } else { | 456 } else { |
| 400 // We are not in an expression context because we have been compiling | 457 // We are not in an expression context because we have been compiling |
| 401 // statements. Set up a test expression context for the condition. | 458 // statements. Set up a test expression context for the condition. |
| 402 ASSERT_EQ(NULL, true_label_); | 459 ASSERT_EQ(NULL, true_label_); |
| 403 ASSERT_EQ(NULL, false_label_); | 460 ASSERT_EQ(NULL, false_label_); |
| 404 | 461 |
| 405 true_label_ = &body; | 462 true_label_ = &body; |
| 406 false_label_ = &exit; | 463 false_label_ = &exit; |
| 407 ASSERT(stmt->cond()->context() == Expression::kTest); | 464 ASSERT(stmt->cond()->context() == Expression::kTest); |
| 408 Visit(stmt->cond()); | 465 Visit(stmt->cond()); |
| 409 true_label_ = NULL; | 466 true_label_ = NULL; |
| 410 false_label_ = NULL; | 467 false_label_ = NULL; |
| 411 } | 468 } |
| 412 | 469 |
| 413 __ bind(&stack_limit_hit); | 470 __ bind(&stack_limit_hit); |
| 414 StackCheckStub stack_stub; | 471 StackCheckStub stack_stub; |
| 415 __ CallStub(&stack_stub); | 472 __ CallStub(&stack_stub); |
| 416 __ jmp(&stack_check_success); | 473 __ jmp(&stack_check_success); |
| 417 | 474 |
| 418 __ bind(&exit); | 475 __ bind(&exit); |
| 476 | |
| 419 decrement_loop_depth(); | 477 decrement_loop_depth(); |
| 420 } | 478 } |
| 421 | 479 |
| 422 | 480 |
| 423 void FastCodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 481 void FastCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 424 UNREACHABLE(); | 482 UNREACHABLE(); |
| 425 } | 483 } |
| 426 | 484 |
| 427 | 485 |
| 428 void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 486 void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 547 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 605 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 548 UNREACHABLE(); | 606 UNREACHABLE(); |
| 549 } | 607 } |
| 550 | 608 |
| 551 | 609 |
| 552 void FastCodeGenerator::VisitThrow(Throw* expr) { | 610 void FastCodeGenerator::VisitThrow(Throw* expr) { |
| 553 UNREACHABLE(); | 611 UNREACHABLE(); |
| 554 } | 612 } |
| 555 | 613 |
| 556 | 614 |
| 615 int FastCodeGenerator::TryFinally::Exit(int stack_depth) { | |
| 616 __ Drop(stack_depth); | |
|
Kevin Millikin (Chromium)
2009/12/10 13:09:26
Good. I much prefer adjusting the stack pointer t
| |
| 617 __ PopTryHandler(); | |
| 618 __ Call(finally_entry_); | |
| 619 return 0; | |
| 620 } | |
| 621 | |
| 622 | |
| 623 int FastCodeGenerator::TryCatch::Exit(int stack_depth) { | |
| 624 __ Drop(stack_depth); | |
| 625 __ PopTryHandler(); | |
| 626 return 0; | |
| 627 } | |
| 628 | |
| 629 | |
| 557 #undef __ | 630 #undef __ |
| 558 | 631 |
| 559 | 632 |
| 560 } } // namespace v8::internal | 633 } } // namespace v8::internal |
| OLD | NEW |