--- parser3/src/main/execute.C 2010/08/11 16:21:52 1.364 +++ parser3/src/main/execute.C 2015/04/08 18:08:53 1.373 @@ -1,12 +1,10 @@ /** @file Parser: executor part of request class. - Copyright (c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_EXECUTE_C="$Date: 2010/08/11 16:21:52 $"; - #include "pa_opcode.h" #include "pa_array.h" #include "pa_request.h" @@ -23,6 +21,8 @@ static const char * const IDENT_EXECUTE_ #include "pa_vimage.h" #include "pa_wwrapper.h" +volatile const char * IDENT_EXECUTE_C="$Id: execute.C,v 1.373 2015/04/08 18:08:53 moko Exp $" IDENT_PA_OPCODE_H IDENT_PA_OPERATION_H IDENT_PA_VCODE_FRAME_H IDENT_PA_WWRAPPER_H; + //#define DEBUG_EXECUTE #ifdef DEBUG_EXECUTE @@ -76,6 +76,10 @@ char *opcode_name[]={ "WITH_SELF__VALUE__CONSTRUCT_VALUE", #endif +#ifdef OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL + "GET_ELEMENT__SPECIAL", + "GET_ELEMENT__SPECIAL__WRITE", +#endif // expression ops: unary "NEG", "INV", "NOT", "DEF", "IN", "FEXISTS", "DEXISTS", // expression ops: binary @@ -263,8 +267,7 @@ void Request::execute(ArrayOperation& op wcontext->set_somebody_entered_some_class(); debug_origin=i.next().origin; - Value& value=*i.next().value; - const String& name=*value.get_string(); debug_name=&name; + const String& name=*i.next().value->get_string(); debug_name=&name; DEBUG_PRINT_STRING(name) @@ -277,6 +280,38 @@ void Request::execute(ArrayOperation& op stack.push(*class_value); break; } + +#ifdef OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL + case OP::OP_GET_ELEMENT__SPECIAL: + case OP::OP_GET_ELEMENT__SPECIAL__WRITE: + { + const String& name=stack.pop().string(); debug_name=&name; + Value& ncontext=stack.pop().value(); + + Value* value=0; + if(VStateless_class* vclass=ncontext.get_class()){ + if(name==class_element_name){ + value=vclass; + } else if(name==class_name_element_name){ + value=new VString(vclass->name()); + } + } else { + // Value + if(name==class_element_name){ + value=&ncontext; + }else if(name==class_name_element_name){ + value=new VString(*new String(ncontext.type())); + } + }; + if(opcode==OP::OP_GET_ELEMENT__SPECIAL){ + stack.push(*value); + } else { + write_assign_lang(*value); + } + break; + } +#endif + // OP_WITH case OP::OP_WITH_ROOT: { @@ -397,7 +432,7 @@ void Request::execute(ArrayOperation& op const String& name=stack.pop().string(); debug_name=&name; Value& ncontext=stack.pop().value(); - if(const VJunction* vjunction=ncontext.put_element(name, &value, false)) + if(const VJunction* vjunction=ncontext.put_element(name, &value)) if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) throw Exception(PARSER_RUNTIME, 0, @@ -639,13 +674,10 @@ void Request::execute(ArrayOperation& op execute(local_ops); - Value* value; // from "$a $b" part of expression taking only string value, // ignoring any other content of wcontext - if(const String* string=wcontext->get_string()) - value=new VString(*string); - else - value=VVoid::get(); + const String* string=wcontext->get_string(); + Value* value=string ? new VString(*string) : new VString(); stack.push(*value); wcontext=saved_wcontext; @@ -723,9 +755,14 @@ void Request::execute(ArrayOperation& op value.type()); } - VMethodFrame frame(*junction->method, method_frame, junction->self); - METHOD_FRAME_ACTION(op_call(frame)); - stack.push(frame.result().as_value()); + Value *result; + { + VMethodFrame frame(*junction->method, method_frame, junction->self); + METHOD_FRAME_ACTION(op_call(frame)); + result=&frame.result().as_value(); + // VMethodFrame desctructor deletes junctions in stack params here + } + stack.push(*result); DEBUG_PRINT_STR("<-returned") @@ -836,15 +873,20 @@ void Request::execute(ArrayOperation& op DEBUG_PRINT_OPS(local_ops) DEBUG_PRINT_STR("->\n") - Value &object=construct(*class_value, *constructor_junction->method); - VConstructorFrame frame(*constructor_junction->method, method_frame, object); - METHOD_FRAME_ACTION(op_call(frame)); - object.enable_default_setter(); + Value *result; + { + Value& object=construct(*class_value, *constructor_junction->method); + VConstructorFrame frame(*constructor_junction->method, method_frame, object); + METHOD_FRAME_ACTION(op_call(frame)); + object.enable_default_setter(); + result=&frame.result().as_value(); + // VMethodFrame desctructor deletes junctions in stack params here + } if(opcode==OP::OP_CONSTRUCT_OBJECT) - stack.push(object); + stack.push(*result); else - write_pass_lang(object); + write_pass_lang(*result); DEBUG_PRINT_STR("<-returned") break; @@ -1207,8 +1249,7 @@ void Request::op_call(VMethodFrame& fram SAVE_CONTEXT - rcontext=wcontext=&frame; - method_frame=&frame; + rcontext=wcontext=method_frame=&frame; Value& self=frame.self(); const Method& method=frame.method; @@ -1272,7 +1313,7 @@ Value& Request::get_element(Value& ncont void Request::put_element(Value& ncontext, const String& name, Value* value) { // put_element can return property-setting-junction - if(const VJunction* vjunction=ncontext.put_element(name, value, false)) + if(const VJunction* vjunction=ncontext.put_element(name, value)) if(vjunction!=PUT_ELEMENT_REPLACED_ELEMENT) { const Junction& junction = vjunction->junction(); VConstructorFrame frame(*junction.method, method_frame /*caller*/, junction.self); @@ -1290,15 +1331,7 @@ void Request::put_element(Value& ncontex frame.store_params(params, 2); Temp_disable_default_setter temp(junction.self); - - SAVE_CONTEXT - - rcontext=wcontext=&frame; - method_frame=&frame; - - recoursion_checked_execute(*frame.method.parser_code); - - RESTORE_CONTEXT + execute_method(frame); } else { // setter if(param_count!=1) @@ -1307,15 +1340,7 @@ void Request::put_element(Value& ncontex "setter method must have ONE parameter (has %d parameters)", param_count); frame.store_params(&value, 1); - - SAVE_CONTEXT - - rcontext=wcontext=&frame; - method_frame=&frame; - - recoursion_checked_execute(*frame.method.parser_code); - - RESTORE_CONTEXT + execute_method(frame); } } } @@ -1338,15 +1363,7 @@ StringOrValue Request::process_getter(Ju } // no need for else frame.empty_params() Temp_disable_default_getter temp(junction.self); - - SAVE_CONTEXT - - rcontext=wcontext=&frame; - method_frame=&frame; - - recoursion_checked_execute(*frame.method.parser_code); // parser code, execute it - - RESTORE_CONTEXT + execute_method(frame); } else { // getter if(param_count!=0) @@ -1355,15 +1372,7 @@ StringOrValue Request::process_getter(Ju "getter method must have no parameters (has %d parameters)", param_count); // no need for frame.empty_params() - - SAVE_CONTEXT - - rcontext=wcontext=&frame; - method_frame=&frame; - - recoursion_checked_execute(*frame.method.parser_code); // parser code, execute it - - RESTORE_CONTEXT + execute_method(frame); } return frame.result(); @@ -1510,51 +1519,37 @@ void Request::process_write(Value& input write_pass_lang(input_value); } -StringOrValue Request::execute_method(VMethodFrame& amethod_frame, const Method& method) { +void Request::execute_method(VMethodFrame& aframe) { SAVE_CONTEXT // initialize contexts - rcontext=wcontext=method_frame=&amethod_frame; + rcontext=wcontext=method_frame=&aframe; // execute! - execute(*method.parser_code); - - // result - StringOrValue result=wcontext->result(); + recoursion_checked_execute(*aframe.method.parser_code); RESTORE_CONTEXT - - // return - return result; } const String* Request::execute_method(Value& aself, const Method& method, Value* optional_param, bool do_return_string) { - SAVE_CONTEXT - VMethodFrame local_frame(method, method_frame/*caller*/, aself); + if(optional_param && local_frame.method_params_count()>0) { local_frame.store_params(&optional_param, 1); } else { local_frame.empty_params(); } - rcontext=wcontext=method_frame=&local_frame; // prevent non-string writes for better error reporting if(do_return_string) local_frame.write(local_frame); - // execute! - execute(*method.parser_code); - - // result - const String* result=do_return_string ? local_frame.get_string() : 0; + execute_method(local_frame); - RESTORE_CONTEXT - - return result; + return do_return_string ? local_frame.get_string() : 0; } Request::Execute_nonvirtual_method_result @@ -1634,6 +1629,7 @@ const String* Request::get_method_filena origin=i.next().origin; break; } + default: break; } if(origin.file_no) return get_used_filename(origin.file_no);