Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <map> | 5 #include <map> |
| 6 #include <set> | 6 #include <set> |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "vm/kernel_to_il.h" | 9 #include "vm/kernel_to_il.h" |
| 10 | 10 |
| (...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1290 | 1290 |
| 1291 ConstantEvaluator::ConstantEvaluator(FlowGraphBuilder* builder, | 1291 ConstantEvaluator::ConstantEvaluator(FlowGraphBuilder* builder, |
| 1292 Zone* zone, | 1292 Zone* zone, |
| 1293 TranslationHelper* h, | 1293 TranslationHelper* h, |
| 1294 DartTypeTranslator* type_translator) | 1294 DartTypeTranslator* type_translator) |
| 1295 : builder_(builder), | 1295 : builder_(builder), |
| 1296 isolate_(Isolate::Current()), | 1296 isolate_(Isolate::Current()), |
| 1297 zone_(zone), | 1297 zone_(zone), |
| 1298 translation_helper_(*h), | 1298 translation_helper_(*h), |
| 1299 type_translator_(*type_translator), | 1299 type_translator_(*type_translator), |
| 1300 script_(dart::Script::Handle( | 1300 script_(Script::Handle( |
| 1301 zone, | 1301 zone, |
| 1302 builder_->parsed_function_->function().script())), | 1302 builder == NULL ? Script::null() |
| 1303 result_(dart::Instance::Handle(zone)) {} | 1303 : builder_->parsed_function_->function().script())), |
| 1304 result_(Instance::Handle(zone)) {} | |
| 1304 | 1305 |
| 1305 | 1306 |
| 1306 Instance& ConstantEvaluator::EvaluateExpression(Expression* expression) { | 1307 Instance& ConstantEvaluator::EvaluateExpression(Expression* expression) { |
| 1307 if (!GetCachedConstant(expression, &result_)) { | 1308 if (!GetCachedConstant(expression, &result_)) { |
| 1308 expression->AcceptExpressionVisitor(this); | 1309 expression->AcceptExpressionVisitor(this); |
| 1309 CacheConstantValue(expression, result_); | 1310 CacheConstantValue(expression, result_); |
| 1310 } | 1311 } |
| 1311 // We return a new `ZoneHandle` here on purpose: The intermediate language | 1312 // We return a new `ZoneHandle` here on purpose: The intermediate language |
| 1312 // instructions do not make a copy of the handle, so we do it. | 1313 // instructions do not make a copy of the handle, so we do it. |
| 1313 return dart::Instance::ZoneHandle(Z, result_.raw()); | 1314 return dart::Instance::ZoneHandle(Z, result_.raw()); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1439 ASSERT(!result.IsError()); | 1440 ASSERT(!result.IsError()); |
| 1440 if (constructor.IsFactory()) { | 1441 if (constructor.IsFactory()) { |
| 1441 // The factory method returns the allocated object. | 1442 // The factory method returns the allocated object. |
| 1442 instance ^= result.raw(); | 1443 instance ^= result.raw(); |
| 1443 } | 1444 } |
| 1444 return H.Canonicalize(instance); | 1445 return H.Canonicalize(instance); |
| 1445 } | 1446 } |
| 1446 | 1447 |
| 1447 | 1448 |
| 1448 bool ConstantEvaluator::GetCachedConstant(TreeNode* node, Instance* value) { | 1449 bool ConstantEvaluator::GetCachedConstant(TreeNode* node, Instance* value) { |
| 1450 if (builder_ == NULL) return false; | |
| 1451 | |
| 1449 const Function& function = builder_->parsed_function_->function(); | 1452 const Function& function = builder_->parsed_function_->function(); |
| 1450 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { | 1453 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { |
| 1451 // Don't cache constants in initializer expressions. They get | 1454 // Don't cache constants in initializer expressions. They get |
| 1452 // evaluated only once. | 1455 // evaluated only once. |
| 1453 return false; | 1456 return false; |
| 1454 } | 1457 } |
| 1455 | 1458 |
| 1456 bool is_present = false; | 1459 bool is_present = false; |
| 1457 ASSERT(!script_.InVMHeap()); | 1460 ASSERT(!script_.InVMHeap()); |
| 1458 if (script_.compile_time_constants() == Array::null()) { | 1461 if (script_.compile_time_constants() == Array::null()) { |
| 1459 return false; | 1462 return false; |
| 1460 } | 1463 } |
| 1461 KernelConstantsMap constants(script_.compile_time_constants()); | 1464 KernelConstantsMap constants(script_.compile_time_constants()); |
| 1462 *value ^= constants.GetOrNull(node, &is_present); | 1465 *value ^= constants.GetOrNull(node, &is_present); |
| 1463 // Mutator compiler thread may add constants while background compiler | 1466 // Mutator compiler thread may add constants while background compiler |
| 1464 // is running, and thus change the value of 'compile_time_constants'; | 1467 // is running, and thus change the value of 'compile_time_constants'; |
| 1465 // do not assert that 'compile_time_constants' has not changed. | 1468 // do not assert that 'compile_time_constants' has not changed. |
| 1466 constants.Release(); | 1469 constants.Release(); |
| 1467 if (FLAG_compiler_stats && is_present) { | 1470 if (FLAG_compiler_stats && is_present) { |
| 1468 H.thread()->compiler_stats()->num_const_cache_hits++; | 1471 H.thread()->compiler_stats()->num_const_cache_hits++; |
| 1469 } | 1472 } |
| 1470 return is_present; | 1473 return is_present; |
| 1471 } | 1474 } |
| 1472 | 1475 |
| 1473 | 1476 |
| 1474 void ConstantEvaluator::CacheConstantValue(TreeNode* node, | 1477 void ConstantEvaluator::CacheConstantValue(TreeNode* node, |
| 1475 const Instance& value) { | 1478 const Instance& value) { |
| 1476 ASSERT(Thread::Current()->IsMutatorThread()); | 1479 ASSERT(Thread::Current()->IsMutatorThread()); |
| 1477 | 1480 |
| 1481 if (builder_ == NULL) return; | |
| 1482 | |
| 1478 const Function& function = builder_->parsed_function_->function(); | 1483 const Function& function = builder_->parsed_function_->function(); |
| 1479 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { | 1484 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { |
| 1480 // Don't cache constants in initializer expressions. They get | 1485 // Don't cache constants in initializer expressions. They get |
| 1481 // evaluated only once. | 1486 // evaluated only once. |
| 1482 return; | 1487 return; |
| 1483 } | 1488 } |
| 1484 const intptr_t kInitialConstMapSize = 16; | 1489 const intptr_t kInitialConstMapSize = 16; |
| 1485 ASSERT(!script_.InVMHeap()); | 1490 ASSERT(!script_.InVMHeap()); |
| 1486 if (script_.compile_time_constants() == Array::null()) { | 1491 if (script_.compile_time_constants() == Array::null()) { |
| 1487 const Array& array = Array::Handle( | 1492 const Array& array = Array::Handle( |
| (...skipping 4372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5860 instructions += StoreInstanceField(Closure::function_offset()); | 5865 instructions += StoreInstanceField(Closure::function_offset()); |
| 5861 | 5866 |
| 5862 instructions += LoadLocal(closure); | 5867 instructions += LoadLocal(closure); |
| 5863 instructions += LoadLocal(parsed_function_->current_context_var()); | 5868 instructions += LoadLocal(parsed_function_->current_context_var()); |
| 5864 instructions += StoreInstanceField(Closure::context_offset()); | 5869 instructions += StoreInstanceField(Closure::context_offset()); |
| 5865 | 5870 |
| 5866 return instructions; | 5871 return instructions; |
| 5867 } | 5872 } |
| 5868 | 5873 |
| 5869 | 5874 |
| 5875 RawObject* EvaluateMetadata(TreeNode* kernel_node) { | |
| 5876 LongJumpScope jump; | |
| 5877 if (setjmp(*jump.Set()) == 0) { | |
| 5878 Thread* thread = Thread::Current(); | |
| 5879 Zone* zone_ = thread->zone(); | |
| 5880 | |
| 5881 List<Expression>* metadata_expressions = NULL; | |
| 5882 if (kernel_node->IsClass()) { | |
| 5883 metadata_expressions = &Class::Cast(kernel_node)->annotations(); | |
| 5884 } else if (kernel_node->IsProcedure()) { | |
| 5885 metadata_expressions = &Procedure::Cast(kernel_node)->annotations(); | |
| 5886 } else if (kernel_node->IsField()) { | |
| 5887 metadata_expressions = &Field::Cast(kernel_node)->annotations(); | |
| 5888 } else if (kernel_node->IsConstructor()) { | |
| 5889 metadata_expressions = &Constructor::Cast(kernel_node)->annotations(); | |
| 5890 } else { | |
| 5891 FATAL1("No support for metadata on this type of kernel node %p\n", | |
| 5892 kernel_node); | |
| 5893 } | |
| 5894 | |
| 5895 TranslationHelper translation_helper(thread); | |
| 5896 DartTypeTranslator type_translator(&translation_helper, NULL, true); | |
| 5897 ConstantEvaluator constant_evaluator(NULL /* flow graph builder */, Z, | |
|
Vyacheslav Egorov (Google)
2017/01/17 22:33:05
Most often we use
/*builder=*/NULL
kind of comm
kustermann
2017/01/18 09:34:41
Done.
| |
| 5898 &translation_helper, &type_translator); | |
| 5899 | |
| 5900 const Array& metadata_values = | |
| 5901 Array::Handle(Z, Array::New(metadata_expressions->length())); | |
| 5902 | |
| 5903 for (intptr_t i = 0; i < metadata_expressions->length(); i++) { | |
| 5904 const Instance& value = | |
| 5905 constant_evaluator.EvaluateExpression((*metadata_expressions)[i]); | |
| 5906 metadata_values.SetAt(i, value); | |
| 5907 } | |
| 5908 | |
| 5909 return metadata_values.raw(); | |
| 5910 } else { | |
| 5911 Thread* thread = Thread::Current(); | |
| 5912 Error& error = Error::Handle(); | |
| 5913 error = thread->sticky_error(); | |
| 5914 thread->clear_sticky_error(); | |
| 5915 return error.raw(); | |
| 5916 } | |
| 5917 } | |
| 5918 | |
| 5919 | |
| 5920 RawObject* BuildParameterDescriptor(TreeNode* kernel_node) { | |
| 5921 LongJumpScope jump; | |
| 5922 if (setjmp(*jump.Set()) == 0) { | |
| 5923 FunctionNode* function_node = NULL; | |
| 5924 | |
| 5925 if (kernel_node->IsProcedure()) { | |
| 5926 function_node = Procedure::Cast(kernel_node)->function(); | |
| 5927 } else if (kernel_node->IsConstructor()) { | |
| 5928 function_node = Constructor::Cast(kernel_node)->function(); | |
| 5929 } else if (kernel_node->IsFunctionNode()) { | |
| 5930 function_node = FunctionNode::Cast(kernel_node); | |
| 5931 } else { | |
| 5932 UNIMPLEMENTED(); | |
| 5933 return NULL; | |
| 5934 } | |
| 5935 | |
| 5936 Thread* thread = Thread::Current(); | |
| 5937 Zone* zone_ = thread->zone(); | |
| 5938 TranslationHelper translation_helper(thread); | |
| 5939 DartTypeTranslator type_translator(&translation_helper, NULL, true); | |
| 5940 ConstantEvaluator constant_evaluator(NULL /* flow graph builder */, Z, | |
|
Vyacheslav Egorov (Google)
2017/01/17 22:33:05
ditto
kustermann
2017/01/18 09:34:41
Done.
| |
| 5941 &translation_helper, &type_translator); | |
| 5942 | |
| 5943 | |
| 5944 intptr_t param_count = function_node->positional_parameters().length() + | |
| 5945 function_node->named_parameters().length(); | |
| 5946 const Array& param_descriptor = Array::Handle( | |
| 5947 Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld)); | |
| 5948 for (intptr_t i = 0; i < param_count; ++i) { | |
| 5949 VariableDeclaration* variable; | |
| 5950 if (i < function_node->positional_parameters().length()) { | |
| 5951 variable = function_node->positional_parameters()[i]; | |
| 5952 } else { | |
| 5953 variable = function_node->named_parameters()[i]; | |
| 5954 } | |
| 5955 | |
| 5956 param_descriptor.SetAt( | |
| 5957 i + Parser::kParameterIsFinalOffset, | |
| 5958 variable->IsFinal() ? Bool::True() : Bool::False()); | |
| 5959 | |
| 5960 if (variable->initializer() != NULL) { | |
| 5961 param_descriptor.SetAt( | |
| 5962 i + Parser::kParameterDefaultValueOffset, | |
| 5963 constant_evaluator.EvaluateExpression(variable->initializer())); | |
| 5964 } else { | |
| 5965 param_descriptor.SetAt(i + Parser::kParameterDefaultValueOffset, | |
| 5966 Object::null_instance()); | |
| 5967 } | |
| 5968 | |
| 5969 param_descriptor.SetAt(i + Parser::kParameterMetadataOffset, | |
| 5970 /* FIXME: No parameter metadata support ATM */ | |
|
Vyacheslav Egorov (Google)
2017/01/17 22:33:05
please file a bug (against dartk?) and use // TODO
kustermann
2017/01/18 09:34:41
Done.
| |
| 5971 Object::null_instance()); | |
| 5972 } | |
| 5973 return param_descriptor.raw(); | |
| 5974 } else { | |
| 5975 Thread* thread = Thread::Current(); | |
| 5976 Error& error = Error::Handle(); | |
| 5977 error = thread->sticky_error(); | |
| 5978 thread->clear_sticky_error(); | |
| 5979 return error.raw(); | |
| 5980 } | |
| 5981 } | |
| 5982 | |
| 5983 | |
| 5870 } // namespace kernel | 5984 } // namespace kernel |
| 5871 } // namespace dart | 5985 } // namespace dart |
| 5986 | |
| 5872 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 5987 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| OLD | NEW |