1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_COMPILER_H_ 29 #define V8_COMPILER_H_ 30 31 #include "ast.h" 32 #include "frame-element.h" 33 #include "parser.h" 34 #include "register-allocator.h" 35 #include "zone.h" 36 37 namespace v8 { 38 namespace internal { 39 40 // CompilationInfo encapsulates some information known at compile time. It 41 // is constructed based on the resources available at compile-time. 42 class CompilationInfo BASE_EMBEDDED { 43 public: 44 // Compilation mode. Either the compiler is used as the primary 45 // compiler and needs to setup everything or the compiler is used as 46 // the secondary compiler for split compilation and has to handle 47 // bailouts. 48 enum Mode { 49 PRIMARY, 50 SECONDARY 51 }; 52 53 // A description of the compilation state at a bailout to the secondary 54 // code generator. 55 // 56 // The state is currently simple: there are no parameters or local 57 // variables to worry about ('this' can be found in the stack frame). 58 // There are at most two live values. 59 // 60 // There is a label that should be bound to the beginning of the bailout 61 // stub code. 62 class Bailout : public ZoneObject { 63 public: 64 Bailout(Register left, Register right) : left_(left), right_(right) {} 65 66 Label* label() { return &label_; } 67 68 private: 69 Register left_; 70 Register right_; 71 Label label_; 72 }; 73 74 75 // Lazy compilation of a JSFunction. 76 CompilationInfo(Handle<JSFunction> closure, 77 int loop_nesting, 78 Handle<Object> receiver) 79 : closure_(closure), 80 function_(NULL), 81 is_eval_(false), 82 loop_nesting_(loop_nesting), 83 receiver_(receiver) { 84 Initialize(); 85 ASSERT(!closure_.is_null() && 86 shared_info_.is_null() && 87 script_.is_null()); 88 } 89 90 // Lazy compilation based on SharedFunctionInfo. 91 explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info) 92 : shared_info_(shared_info), 93 function_(NULL), 94 is_eval_(false), 95 loop_nesting_(0) { 96 Initialize(); 97 ASSERT(closure_.is_null() && 98 !shared_info_.is_null() && 99 script_.is_null()); 100 } 101 102 // Eager compilation. 103 CompilationInfo(FunctionLiteral* literal, Handle<Script> script, bool is_eval) 104 : script_(script), 105 function_(literal), 106 is_eval_(is_eval), 107 loop_nesting_(0) { 108 Initialize(); 109 ASSERT(closure_.is_null() && 110 shared_info_.is_null() && 111 !script_.is_null()); 112 } 113 114 // We can only get a JSFunction if we actually have one. 115 Handle<JSFunction> closure() { return closure_; } 116 117 // We can get a SharedFunctionInfo from a JSFunction or if we actually 118 // have one. 119 Handle<SharedFunctionInfo> shared_info() { 120 if (!closure().is_null()) { 121 return Handle<SharedFunctionInfo>(closure()->shared()); 122 } else { 123 return shared_info_; 124 } 125 } 126 127 // We can always get a script. Either we have one or we can get a shared 128 // function info. 129 Handle<Script> script() { 130 if (!script_.is_null()) { 131 return script_; 132 } else { 133 ASSERT(shared_info()->script()->IsScript()); 134 return Handle<Script>(Script::cast(shared_info()->script())); 135 } 136 } 137 138 // There should always be a function literal, but it may be set after 139 // construction (for lazy compilation). 140 FunctionLiteral* function() { return function_; } 141 void set_function(FunctionLiteral* literal) { 142 ASSERT(function_ == NULL); 143 function_ = literal; 144 } 145 146 // Simple accessors. 147 bool is_eval() { return is_eval_; } 148 int loop_nesting() { return loop_nesting_; } 149 bool has_receiver() { return !receiver_.is_null(); } 150 Handle<Object> receiver() { return receiver_; } 151 List<Bailout*>* bailouts() { return &bailouts_; } 152 153 // Accessors for mutable fields (possibly set by analysis passes) with 154 // default values given by Initialize. 155 Mode mode() { return mode_; } 156 void set_mode(Mode mode) { mode_ = mode; } 157 158 bool has_this_properties() { return has_this_properties_; } 159 void set_has_this_properties(bool flag) { has_this_properties_ = flag; } 160 161 bool has_global_object() { 162 return !closure().is_null() && (closure()->context()->global() != NULL); 163 } 164 165 GlobalObject* global_object() { 166 return has_global_object() ? closure()->context()->global() : NULL; 167 } 168 169 bool has_globals() { return has_globals_; } 170 void set_has_globals(bool flag) { has_globals_ = flag; } 171 172 // Derived accessors. 173 Scope* scope() { return function()->scope(); } 174 175 // Add a bailout with two live values. 176 Label* AddBailout(Register left, Register right) { 177 Bailout* bailout = new Bailout(left, right); 178 bailouts_.Add(bailout); 179 return bailout->label(); 180 } 181 182 // Add a bailout with no live values. 183 Label* AddBailout() { return AddBailout(no_reg, no_reg); } 184 185 private: 186 void Initialize() { 187 mode_ = PRIMARY; 188 has_this_properties_ = false; 189 has_globals_ = false; 190 } 191 192 Handle<JSFunction> closure_; 193 Handle<SharedFunctionInfo> shared_info_; 194 Handle<Script> script_; 195 196 FunctionLiteral* function_; 197 Mode mode_; 198 199 bool is_eval_; 200 int loop_nesting_; 201 202 Handle<Object> receiver_; 203 204 bool has_this_properties_; 205 bool has_globals_; 206 207 // An ordered list of bailout points encountered during fast-path 208 // compilation. 209 List<Bailout*> bailouts_; 210 211 DISALLOW_COPY_AND_ASSIGN(CompilationInfo); 212 }; 213 214 215 // The V8 compiler 216 // 217 // General strategy: Source code is translated into an anonymous function w/o 218 // parameters which then can be executed. If the source code contains other 219 // functions, they will be compiled and allocated as part of the compilation 220 // of the source code. 221 222 // Please note this interface returns function boilerplates. 223 // This means you need to call Factory::NewFunctionFromBoilerplate 224 // before you have a real function with context. 225 226 class Compiler : public AllStatic { 227 public: 228 enum ValidationState { VALIDATE_JSON, DONT_VALIDATE_JSON }; 229 230 // All routines return a JSFunction. 231 // If an error occurs an exception is raised and 232 // the return handle contains NULL. 233 234 // Compile a String source within a context. 235 static Handle<JSFunction> Compile(Handle<String> source, 236 Handle<Object> script_name, 237 int line_offset, int column_offset, 238 v8::Extension* extension, 239 ScriptDataImpl* pre_data, 240 Handle<Object> script_data, 241 NativesFlag is_natives_code); 242 243 // Compile a String source within a context for Eval. 244 static Handle<JSFunction> CompileEval(Handle<String> source, 245 Handle<Context> context, 246 bool is_global, 247 ValidationState validation); 248 249 // Compile from function info (used for lazy compilation). Returns 250 // true on success and false if the compilation resulted in a stack 251 // overflow. 252 static bool CompileLazy(CompilationInfo* info); 253 254 // Compile a function boilerplate object (the function is possibly 255 // lazily compiled). Called recursively from a backend code 256 // generator 'caller' to build the boilerplate. 257 static Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node, 258 Handle<Script> script, 259 AstVisitor* caller); 260 261 // Set the function info for a newly compiled function. 262 static void SetFunctionInfo(Handle<JSFunction> fun, 263 FunctionLiteral* lit, 264 bool is_toplevel, 265 Handle<Script> script); 266 267 private: 268 269 #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT 270 static void LogCodeCreateEvent(Logger::LogEventsAndTags tag, 271 Handle<String> name, 272 Handle<String> inferred_name, 273 int start_position, 274 Handle<Script> script, 275 Handle<Code> code); 276 #endif 277 }; 278 279 280 // During compilation we need a global list of handles to constants 281 // for frame elements. When the zone gets deleted, we make sure to 282 // clear this list of handles as well. 283 class CompilationZoneScope : public ZoneScope { 284 public: 285 explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { } 286 virtual ~CompilationZoneScope() { 287 if (ShouldDeleteOnExit()) { 288 FrameElement::ClearConstantList(); 289 Result::ClearConstantList(); 290 } 291 } 292 }; 293 294 295 } } // namespace v8::internal 296 297 #endif // V8_COMPILER_H_ 298