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 |