OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 } | 95 } |
96 } | 96 } |
97 | 97 |
98 // Generate code and return it. | 98 // Generate code and return it. |
99 Handle<Code> result = CodeGenerator::MakeCode(literal, script, is_eval); | 99 Handle<Code> result = CodeGenerator::MakeCode(literal, script, is_eval); |
100 return result; | 100 return result; |
101 } | 101 } |
102 | 102 |
103 | 103 |
104 static bool IsValidJSON(FunctionLiteral* lit) { | 104 static bool IsValidJSON(FunctionLiteral* lit) { |
105 if (!lit->body()->length() == 1) | 105 if (lit->body()->length() != 1) |
106 return false; | 106 return false; |
107 Statement* stmt = lit->body()->at(0); | 107 Statement* stmt = lit->body()->at(0); |
108 if (stmt->AsExpressionStatement() == NULL) | 108 if (stmt->AsExpressionStatement() == NULL) |
109 return false; | 109 return false; |
110 Expression* expr = stmt->AsExpressionStatement()->expression(); | 110 Expression* expr = stmt->AsExpressionStatement()->expression(); |
111 return expr->IsValidJSON(); | 111 return expr->IsValidJSON(); |
112 } | 112 } |
113 | 113 |
114 | 114 |
115 static Handle<JSFunction> MakeFunction(bool is_global, | 115 static Handle<JSFunction> MakeFunction(bool is_global, |
116 bool is_eval, | 116 bool is_eval, |
117 bool is_json, | 117 Compiler::ValidationState validate, |
118 Handle<Script> script, | 118 Handle<Script> script, |
119 Handle<Context> context, | 119 Handle<Context> context, |
120 v8::Extension* extension, | 120 v8::Extension* extension, |
121 ScriptDataImpl* pre_data) { | 121 ScriptDataImpl* pre_data) { |
122 CompilationZoneScope zone_scope(DELETE_ON_EXIT); | 122 CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
123 | 123 |
124 // Make sure we have an initial stack limit. | 124 // Make sure we have an initial stack limit. |
125 StackGuard guard; | 125 StackGuard guard; |
126 PostponeInterruptsScope postpone; | 126 PostponeInterruptsScope postpone; |
127 | 127 |
128 ASSERT(!i::Top::global_context().is_null()); | 128 ASSERT(!i::Top::global_context().is_null()); |
129 script->set_context_data((*i::Top::global_context())->data()); | 129 script->set_context_data((*i::Top::global_context())->data()); |
130 | 130 |
131 #ifdef ENABLE_DEBUGGER_SUPPORT | 131 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 132 bool is_json = (validate == Compiler::VALIDATE_JSON); |
132 if (is_eval || is_json) { | 133 if (is_eval || is_json) { |
133 script->set_compilation_type( | 134 script->set_compilation_type( |
134 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) : | 135 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) : |
135 Smi::FromInt(Script::COMPILATION_TYPE_EVAL)); | 136 Smi::FromInt(Script::COMPILATION_TYPE_EVAL)); |
136 // For eval scripts add information on the function from which eval was | 137 // For eval scripts add information on the function from which eval was |
137 // called. | 138 // called. |
138 if (is_eval) { | 139 if (is_eval) { |
139 JavaScriptFrameIterator it; | 140 JavaScriptFrameIterator it; |
140 script->set_eval_from_function(it.frame()->function()); | 141 script->set_eval_from_function(it.frame()->function()); |
141 int offset = it.frame()->pc() - it.frame()->code()->instruction_start(); | 142 int offset = it.frame()->pc() - it.frame()->code()->instruction_start(); |
(...skipping 13 matching lines...) Expand all Loading... |
155 | 156 |
156 // Check for parse errors. | 157 // Check for parse errors. |
157 if (lit == NULL) { | 158 if (lit == NULL) { |
158 ASSERT(Top::has_pending_exception()); | 159 ASSERT(Top::has_pending_exception()); |
159 return Handle<JSFunction>::null(); | 160 return Handle<JSFunction>::null(); |
160 } | 161 } |
161 | 162 |
162 // When parsing JSON we do an ordinary parse and then afterwards | 163 // When parsing JSON we do an ordinary parse and then afterwards |
163 // check the AST to ensure it was well-formed. If not we give a | 164 // check the AST to ensure it was well-formed. If not we give a |
164 // syntax error. | 165 // syntax error. |
165 if (is_json && !IsValidJSON(lit)) { | 166 if (validate == Compiler::VALIDATE_JSON && !IsValidJSON(lit)) { |
166 HandleScope scope; | 167 HandleScope scope; |
167 Handle<JSArray> args = Factory::NewJSArray(1); | 168 Handle<JSArray> args = Factory::NewJSArray(1); |
168 Handle<Object> source(script->source()); | 169 Handle<Object> source(script->source()); |
169 SetElement(args, 0, source); | 170 SetElement(args, 0, source); |
170 Handle<Object> result = Factory::NewSyntaxError("invalid_json", args); | 171 Handle<Object> result = Factory::NewSyntaxError("invalid_json", args); |
171 Top::Throw(*result, NULL); | 172 Top::Throw(*result, NULL); |
172 return Handle<JSFunction>::null(); | 173 return Handle<JSFunction>::null(); |
173 } | 174 } |
174 | 175 |
175 // Measure how long it takes to do the compilation; only take the | 176 // Measure how long it takes to do the compilation; only take the |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 Handle<Script> script = Factory::NewScript(source); | 276 Handle<Script> script = Factory::NewScript(source); |
276 if (!script_name.is_null()) { | 277 if (!script_name.is_null()) { |
277 script->set_name(*script_name); | 278 script->set_name(*script_name); |
278 script->set_line_offset(Smi::FromInt(line_offset)); | 279 script->set_line_offset(Smi::FromInt(line_offset)); |
279 script->set_column_offset(Smi::FromInt(column_offset)); | 280 script->set_column_offset(Smi::FromInt(column_offset)); |
280 } | 281 } |
281 | 282 |
282 // Compile the function and add it to the cache. | 283 // Compile the function and add it to the cache. |
283 result = MakeFunction(true, | 284 result = MakeFunction(true, |
284 false, | 285 false, |
285 false, | 286 DONT_VALIDATE_JSON, |
286 script, | 287 script, |
287 Handle<Context>::null(), | 288 Handle<Context>::null(), |
288 extension, | 289 extension, |
289 pre_data); | 290 pre_data); |
290 if (extension == NULL && !result.is_null()) { | 291 if (extension == NULL && !result.is_null()) { |
291 CompilationCache::PutScript(source, result); | 292 CompilationCache::PutScript(source, result); |
292 } | 293 } |
293 | 294 |
294 // Get rid of the pre-parsing data (if necessary). | 295 // Get rid of the pre-parsing data (if necessary). |
295 if (input_pre_data == NULL && pre_data != NULL) { | 296 if (input_pre_data == NULL && pre_data != NULL) { |
296 delete pre_data; | 297 delete pre_data; |
297 } | 298 } |
298 } | 299 } |
299 | 300 |
300 if (result.is_null()) Top::ReportPendingMessages(); | 301 if (result.is_null()) Top::ReportPendingMessages(); |
301 return result; | 302 return result; |
302 } | 303 } |
303 | 304 |
304 | 305 |
305 Handle<JSFunction> Compiler::CompileEval(Handle<String> source, | 306 Handle<JSFunction> Compiler::CompileEval(Handle<String> source, |
306 Handle<Context> context, | 307 Handle<Context> context, |
307 bool is_global, | 308 bool is_global, |
308 bool is_json) { | 309 ValidationState validate) { |
| 310 // Note that if validation is required then no path through this |
| 311 // function is allowed to return a value without validating that |
| 312 // the input is legal json. |
| 313 |
309 int source_length = source->length(); | 314 int source_length = source->length(); |
310 Counters::total_eval_size.Increment(source_length); | 315 Counters::total_eval_size.Increment(source_length); |
311 Counters::total_compile_size.Increment(source_length); | 316 Counters::total_compile_size.Increment(source_length); |
312 | 317 |
313 // The VM is in the COMPILER state until exiting this function. | 318 // The VM is in the COMPILER state until exiting this function. |
314 VMState state(COMPILER); | 319 VMState state(COMPILER); |
315 | 320 |
316 // Do a lookup in the compilation cache; if the entry is not there, | 321 // Do a lookup in the compilation cache; if the entry is not there, |
317 // invoke the compiler and add the result to the cache. | 322 // invoke the compiler and add the result to the cache. If we're |
318 Handle<JSFunction> result = | 323 // evaluating json we bypass the cache since we can't be sure a |
319 CompilationCache::LookupEval(source, context, is_global); | 324 // potential value in the cache has been validated. |
| 325 Handle<JSFunction> result; |
| 326 if (validate == DONT_VALIDATE_JSON) |
| 327 result = CompilationCache::LookupEval(source, context, is_global); |
| 328 |
320 if (result.is_null()) { | 329 if (result.is_null()) { |
321 // Create a script object describing the script to be compiled. | 330 // Create a script object describing the script to be compiled. |
322 Handle<Script> script = Factory::NewScript(source); | 331 Handle<Script> script = Factory::NewScript(source); |
323 result = MakeFunction(is_global, | 332 result = MakeFunction(is_global, |
324 true, | 333 true, |
325 is_json, | 334 validate, |
326 script, | 335 script, |
327 context, | 336 context, |
328 NULL, | 337 NULL, |
329 NULL); | 338 NULL); |
330 if (!result.is_null()) { | 339 if (!result.is_null() && validate != VALIDATE_JSON) { |
| 340 // For json it's unlikely that we'll ever see exactly the same |
| 341 // string again so we don't use the compilation cache. |
331 CompilationCache::PutEval(source, context, is_global, result); | 342 CompilationCache::PutEval(source, context, is_global, result); |
332 } | 343 } |
333 } | 344 } |
334 | 345 |
335 return result; | 346 return result; |
336 } | 347 } |
337 | 348 |
338 | 349 |
339 bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared, | 350 bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared, |
340 int loop_nesting) { | 351 int loop_nesting) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 // Set the expected number of properties for instances. | 428 // Set the expected number of properties for instances. |
418 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); | 429 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); |
419 | 430 |
420 // Check the function has compiled code. | 431 // Check the function has compiled code. |
421 ASSERT(shared->is_compiled()); | 432 ASSERT(shared->is_compiled()); |
422 return true; | 433 return true; |
423 } | 434 } |
424 | 435 |
425 | 436 |
426 } } // namespace v8::internal | 437 } } // namespace v8::internal |
OLD | NEW |