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