| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 #endif | 315 #endif |
| 316 LOG_CODE_EVENT(isolate, | 316 LOG_CODE_EVENT(isolate, |
| 317 CodeStartLinePosInfoRecordEvent(masm.positions_recorder())); | 317 CodeStartLinePosInfoRecordEvent(masm.positions_recorder())); |
| 318 | 318 |
| 319 FullCodeGenerator cgen(&masm, info); | 319 FullCodeGenerator cgen(&masm, info); |
| 320 cgen.Generate(); | 320 cgen.Generate(); |
| 321 if (cgen.HasStackOverflow()) { | 321 if (cgen.HasStackOverflow()) { |
| 322 ASSERT(!isolate->has_pending_exception()); | 322 ASSERT(!isolate->has_pending_exception()); |
| 323 return false; | 323 return false; |
| 324 } | 324 } |
| 325 unsigned table_offset = cgen.EmitStackCheckTable(); | 325 unsigned table_offset = cgen.EmitBackEdgeTable(); |
| 326 | 326 |
| 327 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); | 327 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); |
| 328 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); | 328 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); |
| 329 code->set_optimizable(info->IsOptimizable() && | 329 code->set_optimizable(info->IsOptimizable() && |
| 330 !info->function()->flags()->Contains(kDontOptimize) && | 330 !info->function()->flags()->Contains(kDontOptimize) && |
| 331 info->function()->scope()->AllowsLazyCompilation()); | 331 info->function()->scope()->AllowsLazyCompilation()); |
| 332 cgen.PopulateDeoptimizationData(code); | 332 cgen.PopulateDeoptimizationData(code); |
| 333 cgen.PopulateTypeFeedbackInfo(code); | 333 cgen.PopulateTypeFeedbackInfo(code); |
| 334 cgen.PopulateTypeFeedbackCells(code); | 334 cgen.PopulateTypeFeedbackCells(code); |
| 335 code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); | 335 code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); |
| 336 code->set_handler_table(*cgen.handler_table()); | 336 code->set_handler_table(*cgen.handler_table()); |
| 337 #ifdef ENABLE_DEBUGGER_SUPPORT | 337 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 338 code->set_has_debug_break_slots( | 338 code->set_has_debug_break_slots( |
| 339 info->isolate()->debugger()->IsDebuggerActive()); | 339 info->isolate()->debugger()->IsDebuggerActive()); |
| 340 code->set_compiled_optimizable(info->IsOptimizable()); | 340 code->set_compiled_optimizable(info->IsOptimizable()); |
| 341 #endif // ENABLE_DEBUGGER_SUPPORT | 341 #endif // ENABLE_DEBUGGER_SUPPORT |
| 342 code->set_allow_osr_at_loop_nesting_level(0); | 342 code->set_allow_osr_at_loop_nesting_level(0); |
| 343 code->set_profiler_ticks(0); | 343 code->set_profiler_ticks(0); |
| 344 code->set_stack_check_table_offset(table_offset); | 344 code->set_back_edge_table_offset(table_offset); |
| 345 code->set_stack_check_patched_for_osr(false); | 345 code->set_back_edges_patched_for_osr(false); |
| 346 CodeGenerator::PrintCode(code, info); | 346 CodeGenerator::PrintCode(code, info); |
| 347 info->SetCode(code); // May be an empty handle. | 347 info->SetCode(code); // May be an empty handle. |
| 348 #ifdef ENABLE_GDB_JIT_INTERFACE | 348 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 349 if (FLAG_gdbjit && !code.is_null()) { | 349 if (FLAG_gdbjit && !code.is_null()) { |
| 350 GDBJITLineInfo* lineinfo = | 350 GDBJITLineInfo* lineinfo = |
| 351 masm.positions_recorder()->DetachGDBJITLineInfo(); | 351 masm.positions_recorder()->DetachGDBJITLineInfo(); |
| 352 | 352 |
| 353 GDBJIT(RegisterDetailedLineInfo(*code, lineinfo)); | 353 GDBJIT(RegisterDetailedLineInfo(*code, lineinfo)); |
| 354 } | 354 } |
| 355 #endif | 355 #endif |
| 356 if (!code.is_null()) { | 356 if (!code.is_null()) { |
| 357 void* line_info = | 357 void* line_info = |
| 358 masm.positions_recorder()->DetachJITHandlerData(); | 358 masm.positions_recorder()->DetachJITHandlerData(); |
| 359 LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info)); | 359 LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info)); |
| 360 } | 360 } |
| 361 return !code.is_null(); | 361 return !code.is_null(); |
| 362 } | 362 } |
| 363 | 363 |
| 364 | 364 |
| 365 unsigned FullCodeGenerator::EmitStackCheckTable() { | 365 unsigned FullCodeGenerator::EmitBackEdgeTable() { |
| 366 // The stack check table consists of a length (in number of entries) | 366 // The stack check table consists of a length (in number of entries) |
| 367 // field, and then a sequence of entries. Each entry is a pair of AST id | 367 // field, and then a sequence of entries. Each entry is a pair of AST id |
| 368 // and code-relative pc offset. | 368 // and code-relative pc offset. |
| 369 masm()->Align(kIntSize); | 369 masm()->Align(kIntSize); |
| 370 unsigned offset = masm()->pc_offset(); | 370 unsigned offset = masm()->pc_offset(); |
| 371 unsigned length = stack_checks_.length(); | 371 unsigned length = back_edges_.length(); |
| 372 __ dd(length); | 372 __ dd(length); |
| 373 for (unsigned i = 0; i < length; ++i) { | 373 for (unsigned i = 0; i < length; ++i) { |
| 374 __ dd(stack_checks_[i].id.ToInt()); | 374 __ dd(back_edges_[i].id.ToInt()); |
| 375 __ dd(stack_checks_[i].pc_and_state); | 375 __ dd(back_edges_[i].pc); |
| 376 __ db(back_edges_[i].loop_depth); |
| 376 } | 377 } |
| 377 return offset; | 378 return offset; |
| 378 } | 379 } |
| 379 | 380 |
| 380 | 381 |
| 381 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { | 382 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { |
| 382 // Fill in the deoptimization information. | 383 // Fill in the deoptimization information. |
| 383 ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); | 384 ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); |
| 384 if (!info_->HasDeoptimizationSupport()) return; | 385 if (!info_->HasDeoptimizationSupport()) return; |
| 385 int length = bailout_entries_.length(); | 386 int length = bailout_entries_.length(); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 void FullCodeGenerator::RecordTypeFeedbackCell( | 472 void FullCodeGenerator::RecordTypeFeedbackCell( |
| 472 TypeFeedbackId id, Handle<JSGlobalPropertyCell> cell) { | 473 TypeFeedbackId id, Handle<JSGlobalPropertyCell> cell) { |
| 473 TypeFeedbackCellEntry entry = { id, cell }; | 474 TypeFeedbackCellEntry entry = { id, cell }; |
| 474 type_feedback_cells_.Add(entry, zone()); | 475 type_feedback_cells_.Add(entry, zone()); |
| 475 } | 476 } |
| 476 | 477 |
| 477 | 478 |
| 478 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { | 479 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { |
| 479 // The pc offset does not need to be encoded and packed together with a state. | 480 // The pc offset does not need to be encoded and packed together with a state. |
| 480 ASSERT(masm_->pc_offset() > 0); | 481 ASSERT(masm_->pc_offset() > 0); |
| 481 BailoutEntry entry = { ast_id, static_cast<unsigned>(masm_->pc_offset()) }; | 482 ASSERT(loop_depth() > 0); |
| 482 stack_checks_.Add(entry, zone()); | 483 uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker); |
| 484 BackEdgeEntry entry = |
| 485 { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth }; |
| 486 back_edges_.Add(entry, zone()); |
| 483 } | 487 } |
| 484 | 488 |
| 485 | 489 |
| 486 bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) { | 490 bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) { |
| 487 // Inline smi case inside loops, but not division and modulo which | 491 // Inline smi case inside loops, but not division and modulo which |
| 488 // are too complicated and take up too much space. | 492 // are too complicated and take up too much space. |
| 489 if (op == Token::DIV ||op == Token::MOD) return false; | 493 if (op == Token::DIV ||op == Token::MOD) return false; |
| 490 if (FLAG_always_inline_smi_code) return true; | 494 if (FLAG_always_inline_smi_code) return true; |
| 491 return loop_depth_ > 0; | 495 return loop_depth_ > 0; |
| 492 } | 496 } |
| (...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 // Pop context. | 1248 // Pop context. |
| 1245 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1249 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1246 // Update local stack frame context field. | 1250 // Update local stack frame context field. |
| 1247 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 1251 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 1248 } | 1252 } |
| 1249 | 1253 |
| 1250 | 1254 |
| 1251 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 1255 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 1252 Comment cmnt(masm_, "[ DoWhileStatement"); | 1256 Comment cmnt(masm_, "[ DoWhileStatement"); |
| 1253 SetStatementPosition(stmt); | 1257 SetStatementPosition(stmt); |
| 1254 Label body, stack_check; | 1258 Label body, book_keeping; |
| 1255 | 1259 |
| 1256 Iteration loop_statement(this, stmt); | 1260 Iteration loop_statement(this, stmt); |
| 1257 increment_loop_depth(); | 1261 increment_loop_depth(); |
| 1258 | 1262 |
| 1259 __ bind(&body); | 1263 __ bind(&body); |
| 1260 Visit(stmt->body()); | 1264 Visit(stmt->body()); |
| 1261 | 1265 |
| 1262 // Record the position of the do while condition and make sure it is | 1266 // Record the position of the do while condition and make sure it is |
| 1263 // possible to break on the condition. | 1267 // possible to break on the condition. |
| 1264 __ bind(loop_statement.continue_label()); | 1268 __ bind(loop_statement.continue_label()); |
| 1265 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); | 1269 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); |
| 1266 SetExpressionPosition(stmt->cond(), stmt->condition_position()); | 1270 SetExpressionPosition(stmt->cond(), stmt->condition_position()); |
| 1267 VisitForControl(stmt->cond(), | 1271 VisitForControl(stmt->cond(), |
| 1268 &stack_check, | 1272 &book_keeping, |
| 1269 loop_statement.break_label(), | 1273 loop_statement.break_label(), |
| 1270 &stack_check); | 1274 &book_keeping); |
| 1271 | 1275 |
| 1272 // Check stack before looping. | 1276 // Check stack before looping. |
| 1273 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); | 1277 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); |
| 1274 __ bind(&stack_check); | 1278 __ bind(&book_keeping); |
| 1275 EmitBackEdgeBookkeeping(stmt, &body); | 1279 EmitBackEdgeBookkeeping(stmt, &body); |
| 1276 __ jmp(&body); | 1280 __ jmp(&body); |
| 1277 | 1281 |
| 1278 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1282 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1279 __ bind(loop_statement.break_label()); | 1283 __ bind(loop_statement.break_label()); |
| 1280 decrement_loop_depth(); | 1284 decrement_loop_depth(); |
| 1281 } | 1285 } |
| 1282 | 1286 |
| 1283 | 1287 |
| 1284 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 1288 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 } | 1608 } |
| 1605 | 1609 |
| 1606 return false; | 1610 return false; |
| 1607 } | 1611 } |
| 1608 | 1612 |
| 1609 | 1613 |
| 1610 #undef __ | 1614 #undef __ |
| 1611 | 1615 |
| 1612 | 1616 |
| 1613 } } // namespace v8::internal | 1617 } } // namespace v8::internal |
| OLD | NEW |