OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ast.h" | 7 #include "src/ast.h" |
8 #include "src/ast-numbering.h" | 8 #include "src/ast-numbering.h" |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 if (cgen.HasStackOverflow()) { | 312 if (cgen.HasStackOverflow()) { |
313 DCHECK(!isolate->has_pending_exception()); | 313 DCHECK(!isolate->has_pending_exception()); |
314 return false; | 314 return false; |
315 } | 315 } |
316 unsigned table_offset = cgen.EmitBackEdgeTable(); | 316 unsigned table_offset = cgen.EmitBackEdgeTable(); |
317 | 317 |
318 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); | 318 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); |
319 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); | 319 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); |
320 cgen.PopulateDeoptimizationData(code); | 320 cgen.PopulateDeoptimizationData(code); |
321 cgen.PopulateTypeFeedbackInfo(code); | 321 cgen.PopulateTypeFeedbackInfo(code); |
| 322 cgen.PopulateHandlerTable(code); |
322 code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); | 323 code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); |
323 code->set_has_reloc_info_for_serialization(info->will_serialize()); | 324 code->set_has_reloc_info_for_serialization(info->will_serialize()); |
324 code->set_handler_table(*cgen.handler_table()); | |
325 code->set_compiled_optimizable(info->IsOptimizable()); | 325 code->set_compiled_optimizable(info->IsOptimizable()); |
326 code->set_allow_osr_at_loop_nesting_level(0); | 326 code->set_allow_osr_at_loop_nesting_level(0); |
327 code->set_profiler_ticks(0); | 327 code->set_profiler_ticks(0); |
328 code->set_back_edge_table_offset(table_offset); | 328 code->set_back_edge_table_offset(table_offset); |
329 CodeGenerator::PrintCode(code, info); | 329 CodeGenerator::PrintCode(code, info); |
330 info->SetCode(code); | 330 info->SetCode(code); |
331 void* line_info = masm.positions_recorder()->DetachJITHandlerData(); | 331 void* line_info = masm.positions_recorder()->DetachJITHandlerData(); |
332 LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info)); | 332 LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info)); |
333 | 333 |
334 #ifdef DEBUG | 334 #ifdef DEBUG |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 | 394 |
395 | 395 |
396 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { | 396 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { |
397 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); | 397 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); |
398 info->set_ic_total_count(ic_total_count_); | 398 info->set_ic_total_count(ic_total_count_); |
399 DCHECK(!isolate()->heap()->InNewSpace(*info)); | 399 DCHECK(!isolate()->heap()->InNewSpace(*info)); |
400 code->set_type_feedback_info(*info); | 400 code->set_type_feedback_info(*info); |
401 } | 401 } |
402 | 402 |
403 | 403 |
| 404 void FullCodeGenerator::PopulateHandlerTable(Handle<Code> code) { |
| 405 int handler_table_size = static_cast<int>(handler_table_.size()); |
| 406 Handle<HandlerTable> table = |
| 407 Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( |
| 408 HandlerTable::LengthForRange(handler_table_size), TENURED)); |
| 409 for (int i = 0; i < handler_table_size; ++i) { |
| 410 HandlerTable::CatchPrediction prediction = |
| 411 handler_table_[i].try_catch_depth > 0 ? HandlerTable::CAUGHT |
| 412 : HandlerTable::UNCAUGHT; |
| 413 table->SetRangeStart(i, handler_table_[i].range_start); |
| 414 table->SetRangeEnd(i, handler_table_[i].range_end); |
| 415 table->SetRangeHandler(i, handler_table_[i].handler_offset, prediction); |
| 416 table->SetRangeDepth(i, handler_table_[i].stack_depth); |
| 417 } |
| 418 code->set_handler_table(*table); |
| 419 } |
| 420 |
| 421 |
| 422 int FullCodeGenerator::NewHandlerTableEntry() { |
| 423 int index = static_cast<int>(handler_table_.size()); |
| 424 HandlerTableEntry entry = {0, 0, 0, 0, 0}; |
| 425 handler_table_.push_back(entry); |
| 426 return index; |
| 427 } |
| 428 |
| 429 |
404 bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime( | 430 bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime( |
405 ObjectLiteral* expr) const { | 431 ObjectLiteral* expr) const { |
406 int literal_flags = expr->ComputeFlags(); | 432 int literal_flags = expr->ComputeFlags(); |
407 // FastCloneShallowObjectStub doesn't copy elements, and object literals don't | 433 // FastCloneShallowObjectStub doesn't copy elements, and object literals don't |
408 // support copy-on-write (COW) elements for now. | 434 // support copy-on-write (COW) elements for now. |
409 // TODO(mvstanton): make object literals support COW elements. | 435 // TODO(mvstanton): make object literals support COW elements. |
410 return masm()->serializer_enabled() || | 436 return masm()->serializer_enabled() || |
411 literal_flags != ObjectLiteral::kShallowProperties || | 437 literal_flags != ObjectLiteral::kShallowProperties || |
412 literal_flags != ObjectLiteral::kFastElements || | 438 literal_flags != ObjectLiteral::kFastElements || |
413 expr->properties_count() > | 439 expr->properties_count() > |
(...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 // Restore the context. | 1248 // Restore the context. |
1223 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1249 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
1224 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 1250 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
1225 scope_ = saved_scope; | 1251 scope_ = saved_scope; |
1226 __ jmp(&exit); | 1252 __ jmp(&exit); |
1227 | 1253 |
1228 // Try block code. Sets up the exception handler chain. | 1254 // Try block code. Sets up the exception handler chain. |
1229 __ bind(&try_entry); | 1255 __ bind(&try_entry); |
1230 | 1256 |
1231 try_catch_depth_++; | 1257 try_catch_depth_++; |
1232 EnterTryBlock(stmt->index(), &handler_entry); | 1258 int handler_index = NewHandlerTableEntry(); |
| 1259 EnterTryBlock(handler_index, &handler_entry); |
1233 { TryCatch try_body(this); | 1260 { TryCatch try_body(this); |
1234 Visit(stmt->try_block()); | 1261 Visit(stmt->try_block()); |
1235 } | 1262 } |
1236 ExitTryBlock(stmt->index()); | 1263 ExitTryBlock(handler_index); |
1237 try_catch_depth_--; | 1264 try_catch_depth_--; |
1238 __ bind(&exit); | 1265 __ bind(&exit); |
1239 } | 1266 } |
1240 | 1267 |
1241 | 1268 |
1242 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1269 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
1243 Comment cmnt(masm_, "[ TryFinallyStatement"); | 1270 Comment cmnt(masm_, "[ TryFinallyStatement"); |
1244 SetStatementPosition(stmt); | 1271 SetStatementPosition(stmt); |
1245 // Try finally is compiled by setting up a try-handler on the stack while | 1272 // Try finally is compiled by setting up a try-handler on the stack while |
1246 // executing the try body, and removing it again afterwards. | 1273 // executing the try body, and removing it again afterwards. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 // Finally block implementation. | 1306 // Finally block implementation. |
1280 __ bind(&finally_entry); | 1307 __ bind(&finally_entry); |
1281 EnterFinallyBlock(); | 1308 EnterFinallyBlock(); |
1282 { Finally finally_body(this); | 1309 { Finally finally_body(this); |
1283 Visit(stmt->finally_block()); | 1310 Visit(stmt->finally_block()); |
1284 } | 1311 } |
1285 ExitFinallyBlock(); // Return to the calling code. | 1312 ExitFinallyBlock(); // Return to the calling code. |
1286 | 1313 |
1287 // Set up try handler. | 1314 // Set up try handler. |
1288 __ bind(&try_entry); | 1315 __ bind(&try_entry); |
1289 EnterTryBlock(stmt->index(), &handler_entry); | 1316 int handler_index = NewHandlerTableEntry(); |
| 1317 EnterTryBlock(handler_index, &handler_entry); |
1290 { TryFinally try_body(this, &finally_entry); | 1318 { TryFinally try_body(this, &finally_entry); |
1291 Visit(stmt->try_block()); | 1319 Visit(stmt->try_block()); |
1292 } | 1320 } |
1293 ExitTryBlock(stmt->index()); | 1321 ExitTryBlock(handler_index); |
1294 // Execute the finally block on the way out. Clobber the unpredictable | 1322 // Execute the finally block on the way out. Clobber the unpredictable |
1295 // value in the result register with one that's safe for GC because the | 1323 // value in the result register with one that's safe for GC because the |
1296 // finally block will unconditionally preserve the result register on the | 1324 // finally block will unconditionally preserve the result register on the |
1297 // stack. | 1325 // stack. |
1298 ClearAccumulator(); | 1326 ClearAccumulator(); |
1299 __ Call(&finally_entry); | 1327 __ Call(&finally_entry); |
1300 } | 1328 } |
1301 | 1329 |
1302 | 1330 |
1303 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1331 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 | 1472 |
1445 void FullCodeGenerator::VisitThrow(Throw* expr) { | 1473 void FullCodeGenerator::VisitThrow(Throw* expr) { |
1446 Comment cmnt(masm_, "[ Throw"); | 1474 Comment cmnt(masm_, "[ Throw"); |
1447 VisitForStackValue(expr->exception()); | 1475 VisitForStackValue(expr->exception()); |
1448 SetSourcePosition(expr->position()); | 1476 SetSourcePosition(expr->position()); |
1449 __ CallRuntime(Runtime::kThrow, 1); | 1477 __ CallRuntime(Runtime::kThrow, 1); |
1450 // Never returns here. | 1478 // Never returns here. |
1451 } | 1479 } |
1452 | 1480 |
1453 | 1481 |
1454 void FullCodeGenerator::EnterTryBlock(int index, Label* handler) { | 1482 void FullCodeGenerator::EnterTryBlock(int handler_index, Label* handler) { |
1455 handler_table()->SetRangeStart(index, masm()->pc_offset()); | 1483 HandlerTableEntry* entry = &handler_table_[handler_index]; |
1456 HandlerTable::CatchPrediction prediction = | 1484 entry->range_start = masm()->pc_offset(); |
1457 try_catch_depth_ > 0 ? HandlerTable::CAUGHT : HandlerTable::UNCAUGHT; | 1485 entry->handler_offset = handler->pos(); |
1458 handler_table()->SetRangeHandler(index, handler->pos(), prediction); | 1486 entry->try_catch_depth = try_catch_depth_; |
1459 | 1487 |
1460 // Determine expression stack depth of try statement. | 1488 // Determine expression stack depth of try statement. |
1461 int stack_depth = info_->scope()->num_stack_slots(); // Include stack locals. | 1489 int stack_depth = info_->scope()->num_stack_slots(); // Include stack locals. |
1462 for (NestedStatement* current = nesting_stack_; current != NULL; /*nop*/) { | 1490 for (NestedStatement* current = nesting_stack_; current != NULL; /*nop*/) { |
1463 current = current->AccumulateDepth(&stack_depth); | 1491 current = current->AccumulateDepth(&stack_depth); |
1464 } | 1492 } |
1465 handler_table()->SetRangeDepth(index, stack_depth); | 1493 entry->stack_depth = stack_depth; |
1466 | 1494 |
1467 // Push context onto operand stack. | 1495 // Push context onto operand stack. |
1468 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | 1496 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
1469 __ Push(context_register()); | 1497 __ Push(context_register()); |
1470 } | 1498 } |
1471 | 1499 |
1472 | 1500 |
1473 void FullCodeGenerator::ExitTryBlock(int index) { | 1501 void FullCodeGenerator::ExitTryBlock(int handler_index) { |
1474 handler_table()->SetRangeEnd(index, masm()->pc_offset()); | 1502 HandlerTableEntry* entry = &handler_table_[handler_index]; |
| 1503 entry->range_end = masm()->pc_offset(); |
1475 | 1504 |
1476 // Drop context from operand stack. | 1505 // Drop context from operand stack. |
1477 __ Drop(TryBlockConstant::kElementCount); | 1506 __ Drop(TryBlockConstant::kElementCount); |
1478 } | 1507 } |
1479 | 1508 |
1480 | 1509 |
1481 void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 1510 void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
1482 | 1511 |
1483 | 1512 |
1484 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( | 1513 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1665 codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS); | 1694 codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS); |
1666 codegen_->scope_ = saved_scope_; | 1695 codegen_->scope_ = saved_scope_; |
1667 } | 1696 } |
1668 | 1697 |
1669 | 1698 |
1670 #undef __ | 1699 #undef __ |
1671 | 1700 |
1672 | 1701 |
1673 } // namespace internal | 1702 } // namespace internal |
1674 } // namespace v8 | 1703 } // namespace v8 |
OLD | NEW |