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/compiler.h" | 5 #include "src/compiler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/ast/ast-numbering.h" | 9 #include "src/ast/ast-numbering.h" |
10 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 return parse_info() ? parse_info()->name() : def; \ | 50 return parse_info() ? parse_info()->name() : def; \ |
51 } | 51 } |
52 | 52 |
53 | 53 |
54 PARSE_INFO_GETTER(Handle<Script>, script) | 54 PARSE_INFO_GETTER(Handle<Script>, script) |
55 PARSE_INFO_GETTER(bool, is_eval) | 55 PARSE_INFO_GETTER(bool, is_eval) |
56 PARSE_INFO_GETTER(bool, is_native) | 56 PARSE_INFO_GETTER(bool, is_native) |
57 PARSE_INFO_GETTER(bool, is_module) | 57 PARSE_INFO_GETTER(bool, is_module) |
58 PARSE_INFO_GETTER(FunctionLiteral*, literal) | 58 PARSE_INFO_GETTER(FunctionLiteral*, literal) |
59 PARSE_INFO_GETTER_WITH_DEFAULT(LanguageMode, language_mode, STRICT) | 59 PARSE_INFO_GETTER_WITH_DEFAULT(LanguageMode, language_mode, STRICT) |
60 PARSE_INFO_GETTER_WITH_DEFAULT(Handle<JSFunction>, closure, | |
61 Handle<JSFunction>::null()) | |
62 PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr) | 60 PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr) |
63 PARSE_INFO_GETTER_WITH_DEFAULT(Handle<Context>, context, | 61 PARSE_INFO_GETTER_WITH_DEFAULT(Handle<Context>, context, |
64 Handle<Context>::null()) | 62 Handle<Context>::null()) |
65 PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info) | 63 PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info) |
66 | 64 |
67 #undef PARSE_INFO_GETTER | 65 #undef PARSE_INFO_GETTER |
68 #undef PARSE_INFO_GETTER_WITH_DEFAULT | 66 #undef PARSE_INFO_GETTER_WITH_DEFAULT |
69 | 67 |
70 // A wrapper around a CompilationInfo that detaches the Handles from | 68 // A wrapper around a CompilationInfo that detaches the Handles from |
71 // the underlying DeferredHandleScope and stores them in info_ on | 69 // the underlying DeferredHandleScope and stores them in info_ on |
72 // destruction. | 70 // destruction. |
73 class CompilationHandleScope BASE_EMBEDDED { | 71 class CompilationHandleScope BASE_EMBEDDED { |
74 public: | 72 public: |
75 explicit CompilationHandleScope(CompilationInfo* info) | 73 explicit CompilationHandleScope(CompilationInfo* info) |
76 : deferred_(info->isolate()), info_(info) {} | 74 : deferred_(info->isolate()), info_(info) {} |
77 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } | 75 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } |
78 | 76 |
79 private: | 77 private: |
80 DeferredHandleScope deferred_; | 78 DeferredHandleScope deferred_; |
81 CompilationInfo* info_; | 79 CompilationInfo* info_; |
82 }; | 80 }; |
83 | 81 |
84 // Exactly like a CompilationInfo, except being allocated via {new} and it also | 82 // Exactly like a CompilationInfo, except being allocated via {new} and it also |
85 // creates and enters a Zone on construction and deallocates it on destruction. | 83 // creates and enters a Zone on construction and deallocates it on destruction. |
86 class CompilationInfoWithZone : public CompilationInfo { | 84 class CompilationInfoWithZone : public CompilationInfo { |
87 public: | 85 public: |
88 explicit CompilationInfoWithZone(Handle<JSFunction> function) | 86 explicit CompilationInfoWithZone(Handle<JSFunction> function) |
89 : CompilationInfo(new ParseInfo(&zone_, function)), | 87 : CompilationInfo(new ParseInfo(&zone_, function), function), |
90 zone_(function->GetIsolate()->allocator()) {} | 88 zone_(function->GetIsolate()->allocator()) {} |
91 | 89 |
92 // Virtual destructor because a CompilationInfoWithZone has to exit the | 90 // Virtual destructor because a CompilationInfoWithZone has to exit the |
93 // zone scope and get rid of dependent maps even when the destructor is | 91 // zone scope and get rid of dependent maps even when the destructor is |
94 // called when cast as a CompilationInfo. | 92 // called when cast as a CompilationInfo. |
95 virtual ~CompilationInfoWithZone() { | 93 virtual ~CompilationInfoWithZone() { |
96 DisableFutureOptimization(); | 94 DisableFutureOptimization(); |
97 dependencies()->Rollback(); | 95 dependencies()->Rollback(); |
98 delete parse_info_; | 96 delete parse_info_; |
99 parse_info_ = nullptr; | 97 parse_info_ = nullptr; |
100 } | 98 } |
101 | 99 |
102 private: | 100 private: |
103 Zone zone_; | 101 Zone zone_; |
104 }; | 102 }; |
105 | 103 |
106 // ---------------------------------------------------------------------------- | 104 // ---------------------------------------------------------------------------- |
107 // Implementation of CompilationInfo | 105 // Implementation of CompilationInfo |
108 | 106 |
109 bool CompilationInfo::has_shared_info() const { | 107 bool CompilationInfo::has_shared_info() const { |
110 return parse_info_ && !parse_info_->shared_info().is_null(); | 108 return parse_info_ && !parse_info_->shared_info().is_null(); |
111 } | 109 } |
112 | 110 |
113 | 111 CompilationInfo::CompilationInfo(ParseInfo* parse_info, |
114 CompilationInfo::CompilationInfo(ParseInfo* parse_info) | 112 Handle<JSFunction> closure) |
115 : CompilationInfo(parse_info, nullptr, Code::ComputeFlags(Code::FUNCTION), | 113 : CompilationInfo(parse_info, nullptr, Code::ComputeFlags(Code::FUNCTION), |
116 BASE, parse_info->isolate(), parse_info->zone()) { | 114 BASE, parse_info->isolate(), parse_info->zone()) { |
| 115 closure_ = closure; |
| 116 |
117 // Compiling for the snapshot typically results in different code than | 117 // Compiling for the snapshot typically results in different code than |
118 // compiling later on. This means that code recompiled with deoptimization | 118 // compiling later on. This means that code recompiled with deoptimization |
119 // support won't be "equivalent" (as defined by SharedFunctionInfo:: | 119 // support won't be "equivalent" (as defined by SharedFunctionInfo:: |
120 // EnableDeoptimizationSupport), so it will replace the old code and all | 120 // EnableDeoptimizationSupport), so it will replace the old code and all |
121 // its type feedback. To avoid this, always compile functions in the snapshot | 121 // its type feedback. To avoid this, always compile functions in the snapshot |
122 // with deoptimization support. | 122 // with deoptimization support. |
123 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport(); | 123 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport(); |
124 | 124 |
125 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing(); | 125 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing(); |
126 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); | 126 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); |
(...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1109 } | 1109 } |
1110 | 1110 |
1111 | 1111 |
1112 bool CompileEvalForDebugging(Handle<JSFunction> function, | 1112 bool CompileEvalForDebugging(Handle<JSFunction> function, |
1113 Handle<SharedFunctionInfo> shared) { | 1113 Handle<SharedFunctionInfo> shared) { |
1114 Handle<Script> script(Script::cast(shared->script())); | 1114 Handle<Script> script(Script::cast(shared->script())); |
1115 Handle<Context> context(function->context()); | 1115 Handle<Context> context(function->context()); |
1116 | 1116 |
1117 Zone zone(function->GetIsolate()->allocator()); | 1117 Zone zone(function->GetIsolate()->allocator()); |
1118 ParseInfo parse_info(&zone, script); | 1118 ParseInfo parse_info(&zone, script); |
1119 CompilationInfo info(&parse_info); | 1119 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
1120 Isolate* isolate = info.isolate(); | 1120 Isolate* isolate = info.isolate(); |
1121 | 1121 |
1122 parse_info.set_eval(); | 1122 parse_info.set_eval(); |
1123 parse_info.set_context(context); | 1123 parse_info.set_context(context); |
1124 if (context->IsNativeContext()) parse_info.set_global(); | 1124 if (context->IsNativeContext()) parse_info.set_global(); |
1125 parse_info.set_toplevel(); | 1125 parse_info.set_toplevel(); |
1126 parse_info.set_allow_lazy_parsing(false); | 1126 parse_info.set_allow_lazy_parsing(false); |
1127 parse_info.set_language_mode(shared->language_mode()); | 1127 parse_info.set_language_mode(shared->language_mode()); |
1128 parse_info.set_parse_restriction(NO_PARSE_RESTRICTION); | 1128 parse_info.set_parse_restriction(NO_PARSE_RESTRICTION); |
1129 info.MarkAsDebug(); | 1129 info.MarkAsDebug(); |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1370 CompilationInfoWithZone info(function); | 1370 CompilationInfoWithZone info(function); |
1371 return CompileForDebugging(&info); | 1371 return CompileForDebugging(&info); |
1372 } | 1372 } |
1373 } | 1373 } |
1374 | 1374 |
1375 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) { | 1375 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) { |
1376 DCHECK(shared->allows_lazy_compilation_without_context()); | 1376 DCHECK(shared->allows_lazy_compilation_without_context()); |
1377 DCHECK(!IsEvalToplevel(shared)); | 1377 DCHECK(!IsEvalToplevel(shared)); |
1378 Zone zone(shared->GetIsolate()->allocator()); | 1378 Zone zone(shared->GetIsolate()->allocator()); |
1379 ParseInfo parse_info(&zone, shared); | 1379 ParseInfo parse_info(&zone, shared); |
1380 CompilationInfo info(&parse_info); | 1380 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
1381 return CompileForDebugging(&info); | 1381 return CompileForDebugging(&info); |
1382 } | 1382 } |
1383 | 1383 |
1384 // TODO(turbofan): In the future, unoptimized code with deopt support could | 1384 // TODO(turbofan): In the future, unoptimized code with deopt support could |
1385 // be generated lazily once deopt is triggered. | 1385 // be generated lazily once deopt is triggered. |
1386 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { | 1386 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { |
1387 DCHECK_NOT_NULL(info->literal()); | 1387 DCHECK_NOT_NULL(info->literal()); |
1388 DCHECK_NOT_NULL(info->scope()); | 1388 DCHECK_NOT_NULL(info->scope()); |
1389 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1389 Handle<SharedFunctionInfo> shared = info->shared_info(); |
1390 if (!shared->has_deoptimization_support()) { | 1390 if (!shared->has_deoptimization_support()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1422 // The existing unoptimized code was replaced with the new one. | 1422 // The existing unoptimized code was replaced with the new one. |
1423 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); | 1423 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); |
1424 } | 1424 } |
1425 return true; | 1425 return true; |
1426 } | 1426 } |
1427 | 1427 |
1428 void Compiler::CompileForLiveEdit(Handle<Script> script) { | 1428 void Compiler::CompileForLiveEdit(Handle<Script> script) { |
1429 // TODO(635): support extensions. | 1429 // TODO(635): support extensions. |
1430 Zone zone(script->GetIsolate()->allocator()); | 1430 Zone zone(script->GetIsolate()->allocator()); |
1431 ParseInfo parse_info(&zone, script); | 1431 ParseInfo parse_info(&zone, script); |
1432 CompilationInfo info(&parse_info); | 1432 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
1433 PostponeInterruptsScope postpone(info.isolate()); | 1433 PostponeInterruptsScope postpone(info.isolate()); |
1434 VMState<COMPILER> state(info.isolate()); | 1434 VMState<COMPILER> state(info.isolate()); |
1435 | 1435 |
1436 // Get rid of old list of shared function infos. | 1436 // Get rid of old list of shared function infos. |
1437 info.MarkAsFirstCompile(); | 1437 info.MarkAsFirstCompile(); |
1438 info.MarkAsDebug(); | 1438 info.MarkAsDebug(); |
1439 info.parse_info()->set_global(); | 1439 info.parse_info()->set_global(); |
1440 if (!Parser::ParseStatic(info.parse_info())) return; | 1440 if (!Parser::ParseStatic(info.parse_info())) return; |
1441 | 1441 |
1442 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal()); | 1442 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal()); |
(...skipping 21 matching lines...) Expand all Loading... |
1464 if (!maybe_shared_info.ToHandle(&shared_info)) { | 1464 if (!maybe_shared_info.ToHandle(&shared_info)) { |
1465 script = isolate->factory()->NewScript(source); | 1465 script = isolate->factory()->NewScript(source); |
1466 if (!script_name.is_null()) { | 1466 if (!script_name.is_null()) { |
1467 script->set_name(*script_name); | 1467 script->set_name(*script_name); |
1468 script->set_line_offset(line_offset); | 1468 script->set_line_offset(line_offset); |
1469 script->set_column_offset(column_offset); | 1469 script->set_column_offset(column_offset); |
1470 } | 1470 } |
1471 script->set_origin_options(options); | 1471 script->set_origin_options(options); |
1472 Zone zone(isolate->allocator()); | 1472 Zone zone(isolate->allocator()); |
1473 ParseInfo parse_info(&zone, script); | 1473 ParseInfo parse_info(&zone, script); |
1474 CompilationInfo info(&parse_info); | 1474 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
1475 parse_info.set_eval(); | 1475 parse_info.set_eval(); |
1476 if (context->IsNativeContext()) parse_info.set_global(); | 1476 if (context->IsNativeContext()) parse_info.set_global(); |
1477 parse_info.set_language_mode(language_mode); | 1477 parse_info.set_language_mode(language_mode); |
1478 parse_info.set_parse_restriction(restriction); | 1478 parse_info.set_parse_restriction(restriction); |
1479 parse_info.set_context(context); | 1479 parse_info.set_context(context); |
1480 | 1480 |
1481 Debug::RecordEvalCaller(script); | 1481 Debug::RecordEvalCaller(script); |
1482 | 1482 |
1483 shared_info = CompileToplevel(&info); | 1483 shared_info = CompileToplevel(&info); |
1484 | 1484 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 script->set_column_offset(column_offset); | 1588 script->set_column_offset(column_offset); |
1589 } | 1589 } |
1590 script->set_origin_options(resource_options); | 1590 script->set_origin_options(resource_options); |
1591 if (!source_map_url.is_null()) { | 1591 if (!source_map_url.is_null()) { |
1592 script->set_source_mapping_url(*source_map_url); | 1592 script->set_source_mapping_url(*source_map_url); |
1593 } | 1593 } |
1594 | 1594 |
1595 // Compile the function and add it to the cache. | 1595 // Compile the function and add it to the cache. |
1596 Zone zone(isolate->allocator()); | 1596 Zone zone(isolate->allocator()); |
1597 ParseInfo parse_info(&zone, script); | 1597 ParseInfo parse_info(&zone, script); |
1598 CompilationInfo info(&parse_info); | 1598 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
1599 if (is_module) { | 1599 if (is_module) { |
1600 parse_info.set_module(); | 1600 parse_info.set_module(); |
1601 } else { | 1601 } else { |
1602 parse_info.set_global(); | 1602 parse_info.set_global(); |
1603 } | 1603 } |
1604 if (compile_options != ScriptCompiler::kNoCompileOptions) { | 1604 if (compile_options != ScriptCompiler::kNoCompileOptions) { |
1605 parse_info.set_cached_data(cached_data); | 1605 parse_info.set_cached_data(cached_data); |
1606 } | 1606 } |
1607 parse_info.set_compile_options(compile_options); | 1607 parse_info.set_compile_options(compile_options); |
1608 parse_info.set_extension(extension); | 1608 parse_info.set_extension(extension); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1645 Handle<Script> script, ParseInfo* parse_info, int source_length) { | 1645 Handle<Script> script, ParseInfo* parse_info, int source_length) { |
1646 Isolate* isolate = script->GetIsolate(); | 1646 Isolate* isolate = script->GetIsolate(); |
1647 // TODO(titzer): increment the counters in caller. | 1647 // TODO(titzer): increment the counters in caller. |
1648 isolate->counters()->total_load_size()->Increment(source_length); | 1648 isolate->counters()->total_load_size()->Increment(source_length); |
1649 isolate->counters()->total_compile_size()->Increment(source_length); | 1649 isolate->counters()->total_compile_size()->Increment(source_length); |
1650 | 1650 |
1651 LanguageMode language_mode = construct_language_mode(FLAG_use_strict); | 1651 LanguageMode language_mode = construct_language_mode(FLAG_use_strict); |
1652 parse_info->set_language_mode( | 1652 parse_info->set_language_mode( |
1653 static_cast<LanguageMode>(parse_info->language_mode() | language_mode)); | 1653 static_cast<LanguageMode>(parse_info->language_mode() | language_mode)); |
1654 | 1654 |
1655 CompilationInfo compile_info(parse_info); | 1655 CompilationInfo compile_info(parse_info, Handle<JSFunction>::null()); |
1656 | 1656 |
1657 // The source was parsed lazily, so compiling for debugging is not possible. | 1657 // The source was parsed lazily, so compiling for debugging is not possible. |
1658 DCHECK(!compile_info.is_debug()); | 1658 DCHECK(!compile_info.is_debug()); |
1659 | 1659 |
1660 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info); | 1660 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info); |
1661 if (!result.is_null()) isolate->debug()->OnAfterCompile(script); | 1661 if (!result.is_null()) isolate->debug()->OnAfterCompile(script); |
1662 return result; | 1662 return result; |
1663 } | 1663 } |
1664 | 1664 |
1665 | 1665 |
(...skipping 26 matching lines...) Expand all Loading... |
1692 | 1692 |
1693 // Allocate a shared function info object. | 1693 // Allocate a shared function info object. |
1694 Handle<SharedFunctionInfo> result; | 1694 Handle<SharedFunctionInfo> result; |
1695 if (!maybe_existing.ToHandle(&result)) { | 1695 if (!maybe_existing.ToHandle(&result)) { |
1696 result = NewSharedFunctionInfoForLiteral(isolate, literal, script); | 1696 result = NewSharedFunctionInfoForLiteral(isolate, literal, script); |
1697 result->set_is_toplevel(false); | 1697 result->set_is_toplevel(false); |
1698 } | 1698 } |
1699 | 1699 |
1700 Zone zone(isolate->allocator()); | 1700 Zone zone(isolate->allocator()); |
1701 ParseInfo parse_info(&zone, script); | 1701 ParseInfo parse_info(&zone, script); |
1702 CompilationInfo info(&parse_info); | 1702 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
1703 parse_info.set_literal(literal); | 1703 parse_info.set_literal(literal); |
1704 parse_info.set_shared_info(result); | 1704 parse_info.set_shared_info(result); |
1705 parse_info.set_scope(literal->scope()); | 1705 parse_info.set_scope(literal->scope()); |
1706 parse_info.set_language_mode(literal->scope()->language_mode()); | 1706 parse_info.set_language_mode(literal->scope()->language_mode()); |
1707 if (outer_info->will_serialize()) info.PrepareForSerializing(); | 1707 if (outer_info->will_serialize()) info.PrepareForSerializing(); |
1708 if (outer_info->is_first_compile()) info.MarkAsFirstCompile(); | 1708 if (outer_info->is_first_compile()) info.MarkAsFirstCompile(); |
1709 if (outer_info->is_debug()) info.MarkAsDebug(); | 1709 if (outer_info->is_debug()) info.MarkAsDebug(); |
1710 | 1710 |
1711 LiveEditFunctionTracker live_edit_tracker(isolate, literal); | 1711 LiveEditFunctionTracker live_edit_tracker(isolate, literal); |
1712 // Determine if the function can be lazily compiled. This is necessary to | 1712 // Determine if the function can be lazily compiled. This is necessary to |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1896 MaybeHandle<Code> code; | 1896 MaybeHandle<Code> code; |
1897 if (cached.code != nullptr) code = handle(cached.code); | 1897 if (cached.code != nullptr) code = handle(cached.code); |
1898 Handle<Context> native_context(function->context()->native_context()); | 1898 Handle<Context> native_context(function->context()->native_context()); |
1899 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1899 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
1900 literals, BailoutId::None()); | 1900 literals, BailoutId::None()); |
1901 } | 1901 } |
1902 } | 1902 } |
1903 | 1903 |
1904 } // namespace internal | 1904 } // namespace internal |
1905 } // namespace v8 | 1905 } // namespace v8 |
OLD | NEW |