Chromium Code Reviews| Index: runtime/vm/object.cc |
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
| index 806399a92d9383e289b394eabd2067eb56993b33..79bb01ab055721355da38b8cbe74f46e263ccd4d 100644 |
| --- a/runtime/vm/object.cc |
| +++ b/runtime/vm/object.cc |
| @@ -2743,51 +2743,37 @@ static RawString* BuildClosureSource(const Array& formal_params, |
| } |
| -static RawPatchClass* MakeTempPatchClass(const Class& cls, |
| - const String& expr, |
| - const Array& formal_params) { |
| +static RawFunction* EvaluateHelper(const Class& cls, |
| + const String& expr, |
| + const Array& param_names, |
| + bool is_static) { |
| const String& func_src = |
| - String::Handle(BuildClosureSource(formal_params, expr)); |
| + String::Handle(BuildClosureSource(param_names, expr)); |
| Script& script = Script::Handle(); |
| script = Script::New(Symbols::Empty(), func_src, RawScript::kSourceTag); |
| // In order to tokenize the source, we need to get the key to mangle |
| - // private names from the library from which the object's class |
| - // originates. |
| + // private names from the library from which the class originates. |
| const Library& lib = Library::Handle(cls.library()); |
| ASSERT(!lib.IsNull()); |
| const String& lib_key = String::Handle(lib.private_key()); |
| script.Tokenize(lib_key); |
| - const String& src_class_name = String::Handle(Symbols::New(":internal")); |
| - const Class& src_class = Class::Handle( |
| - Class::New(src_class_name, script, Scanner::kNoSourcePos)); |
| - src_class.set_is_finalized(); |
| - src_class.set_library(lib); |
| - return PatchClass::New(cls, src_class); |
| + const Function& func = Function::Handle( |
| + Function::NewEvalFunction(cls, script, is_static)); |
| + func.set_result_type(Type::Handle(Type::DynamicType())); |
| + const intptr_t num_implicit_params = is_static ? 0 : 1; |
| + func.set_num_fixed_parameters(num_implicit_params + param_names.Length()); |
| + func.SetNumOptionalParameters(0, true); |
| + func.SetIsOptimizable(false); |
| + return func.raw(); |
| } |
| RawObject* Class::Evaluate(const String& expr, |
| const Array& param_names, |
| const Array& param_values) const { |
| - const PatchClass& temp_class = |
| - PatchClass::Handle(MakeTempPatchClass(*this, expr, param_names)); |
| - const String& eval_func_name = String::Handle(Symbols::New(":eval")); |
| const Function& eval_func = |
| - Function::Handle(Function::New(eval_func_name, |
| - RawFunction::kRegularFunction, |
| - true, // Static. |
| - false, // Not const. |
| - false, // Not abstract. |
| - false, // Not external. |
| - false, // Not native. |
| - temp_class, |
| - 0)); |
| - eval_func.set_result_type(Type::Handle(Type::DynamicType())); |
| - eval_func.set_num_fixed_parameters(param_names.Length()); |
| - eval_func.SetNumOptionalParameters(0, true); |
| - eval_func.SetIsOptimizable(false); |
| - |
| + Function::Handle(EvaluateHelper(*this, expr, param_names, true)); |
| const Object& result = |
| Object::Handle(DartEntry::InvokeFunction(eval_func, param_values)); |
| return result.raw(); |
| @@ -5073,6 +5059,22 @@ void Function::set_implicit_static_closure(const Instance& closure) const { |
| } |
| +RawScript* Function::eval_script() const { |
| + const Object& obj = Object::Handle(raw_ptr()->data_); |
| + if (obj.IsScript()) { |
| + return Script::Cast(obj).raw(); |
| + } |
| + return Script::null(); |
| +} |
| + |
| + |
| +void Function::set_eval_script(const Script& script) const { |
| + ASSERT(token_pos() == 0); |
| + ASSERT(Object::Handle(raw_ptr()->data_).IsNull()); |
|
hausner
2014/07/10 22:57:27
Don't allocate a handle just for the assertion. De
|
| + set_data(script); |
| +} |
| + |
| + |
| RawFunction* Function::extracted_method_closure() const { |
| ASSERT(kind() == RawFunction::kMethodExtractor); |
| const Object& obj = Object::Handle(raw_ptr()->data_); |
| @@ -5149,13 +5151,15 @@ RawFunction* Function::implicit_closure_function() const { |
| return Function::null(); |
| } |
| const Object& obj = Object::Handle(raw_ptr()->data_); |
| - ASSERT(obj.IsNull() || obj.IsFunction()); |
| - return (obj.IsNull()) ? Function::null() : Function::Cast(obj).raw(); |
| + ASSERT(obj.IsNull() || obj.IsScript() || obj.IsFunction()); |
| + return (obj.IsNull() || obj.IsScript()) ? Function::null() |
| + : Function::Cast(obj).raw(); |
| } |
| void Function::set_implicit_closure_function(const Function& value) const { |
| ASSERT(!IsClosureFunction() && !IsSignatureFunction()); |
| + ASSERT(Object::Handle(raw_ptr()->data_).IsNull()); |
|
hausner
2014/07/10 22:57:27
ditto.
|
| set_data(value); |
| } |
| @@ -6079,11 +6083,29 @@ RawFunction* Function::NewClosureFunction(const String& name, |
| parent_owner, |
| token_pos)); |
| result.set_parent_function(parent); |
| - |
| return result.raw(); |
| } |
| +RawFunction* Function::NewEvalFunction(const Class& owner, |
| + const Script& script, |
| + bool is_static) { |
| + ASSERT(!owner.IsNull()); |
|
hausner
2014/07/10 22:57:27
This will be asserted again in Function::New(). I
rmacnak
2014/07/10 23:17:37
Removed.
|
| + ASSERT(!script.IsNull()); |
| + const Function& result = Function::Handle( |
| + Function::New(String::Handle(Symbols::New(":Eval")), |
| + RawFunction::kRegularFunction, |
| + is_static, |
| + /* is_const = */ false, |
| + /* is_abstract = */ false, |
| + /* is_external = */ false, |
| + /* is_native = */ false, |
| + owner, |
| + 0)); |
| + result.set_eval_script(script); |
| + return result.raw(); |
| +} |
| + |
| RawFunction* Function::ImplicitClosureFunction() const { |
| // Return the existing implicit closure function if any. |
| if (implicit_closure_function() != Function::null()) { |
| @@ -6349,6 +6371,15 @@ RawClass* Function::origin() const { |
| RawScript* Function::script() const { |
| + if (token_pos() == 0) { |
|
hausner
2014/07/10 22:57:27
Maybe add a comment that this check for position 0
rmacnak
2014/07/10 23:17:37
Added.
|
| + const Script& script = Script::Handle(eval_script()); |
| + if (!script.IsNull()) { |
| + return script.raw(); |
| + } |
| + } |
| + if (IsClosureFunction()) { |
| + return Function::Handle(parent_function()).script(); |
| + } |
| const Object& obj = Object::Handle(raw_ptr()->owner_); |
| if (obj.IsClass()) { |
| return Class::Cast(obj).script(); |
| @@ -9276,17 +9307,25 @@ void Library::InitCoreLibrary(Isolate* isolate) { |
| RawObject* Library::Evaluate(const String& expr, |
| const Array& param_names, |
| const Array& param_values) const { |
| - // Make a fake top-level class and evaluate the expression |
| + // Take or make a fake top-level class and evaluate the expression |
| // as a static function of the class. |
| - Script& script = Script::Handle(); |
| - script = Script::New(Symbols::Empty(), |
| - Symbols::Empty(), |
| - RawScript::kSourceTag); |
| - Class& temp_class = |
| - Class::Handle(Class::New(Symbols::TopLevel(), script, 0)); |
| - temp_class.set_library(*this); |
| - temp_class.set_is_finalized(); |
| - return temp_class.Evaluate(expr, param_names, param_values); |
| + Class& top_level_class = Class::Handle(); |
| + Array& top_level_classes = Array::Handle(anonymous_classes()); |
| + if (top_level_classes.Length() > 0) { |
| + top_level_class ^= top_level_classes.At(0); |
| + } else { |
| + // A library may have no top-level classes if it has no top-level |
| + // variables or methods. |
| + Script& script = Script::Handle(Script::New(Symbols::Empty(), |
| + Symbols::Empty(), |
| + RawScript::kSourceTag)); |
| + top_level_class = Class::New(Symbols::TopLevel(), script, 0); |
| + top_level_class.set_is_finalized(); |
| + top_level_class.set_library(*this); |
| + AddAnonymousClass(top_level_class); |
| + } |
| + ASSERT(top_level_class.is_finalized()); |
| + return top_level_class.Evaluate(expr, param_names, param_values); |
| } |
| @@ -12762,24 +12801,8 @@ RawObject* Instance::Evaluate(const String& expr, |
| const Array& param_names, |
| const Array& param_values) const { |
| const Class& cls = Class::Handle(clazz()); |
| - const PatchClass& temp_class = PatchClass::Handle( |
| - MakeTempPatchClass(cls, expr, param_names)); |
| - const String& eval_func_name = String::Handle(Symbols::New(":eval")); |
| const Function& eval_func = |
| - Function::Handle(Function::New(eval_func_name, |
| - RawFunction::kRegularFunction, |
| - false, // Not static. |
| - false, // Not const. |
| - false, // Not abstract. |
| - false, // Not external. |
| - false, // Not native. |
| - temp_class, |
| - 0)); |
| - eval_func.set_result_type(Type::Handle(Type::DynamicType())); |
| - eval_func.set_num_fixed_parameters(1 + param_values.Length()); |
| - eval_func.SetNumOptionalParameters(0, true); |
| - eval_func.SetIsOptimizable(false); |
| - |
| + Function::Handle(EvaluateHelper(cls, expr, param_names, false)); |
| const Array& args = Array::Handle(Array::New(1 + param_values.Length())); |
| Object& param = Object::Handle(); |
| args.SetAt(0, *this); |