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 20 matching lines...) Expand all Loading... |
31 #include "compiler.h" | 31 #include "compiler.h" |
32 #include "full-codegen.h" | 32 #include "full-codegen.h" |
33 #include "scopes.h" | 33 #include "scopes.h" |
34 #include "stub-cache.h" | 34 #include "stub-cache.h" |
35 #include "debug.h" | 35 #include "debug.h" |
36 #include "liveedit.h" | 36 #include "liveedit.h" |
37 | 37 |
38 namespace v8 { | 38 namespace v8 { |
39 namespace internal { | 39 namespace internal { |
40 | 40 |
41 #define BAILOUT(reason) \ | |
42 do { \ | |
43 if (FLAG_trace_bailout) { \ | |
44 PrintF("%s\n", reason); \ | |
45 } \ | |
46 has_supported_syntax_ = false; \ | |
47 return; \ | |
48 } while (false) | |
49 | |
50 | |
51 #define CHECK_BAILOUT \ | |
52 do { \ | |
53 if (!has_supported_syntax_) return; \ | |
54 } while (false) | |
55 | |
56 | |
57 void FullCodeGenSyntaxChecker::Check(FunctionLiteral* fun) { | |
58 Scope* scope = fun->scope(); | |
59 VisitDeclarations(scope->declarations()); | |
60 CHECK_BAILOUT; | |
61 | |
62 VisitStatements(fun->body()); | |
63 } | |
64 | |
65 | |
66 void FullCodeGenSyntaxChecker::VisitDeclarations( | |
67 ZoneList<Declaration*>* decls) { | |
68 for (int i = 0; i < decls->length(); i++) { | |
69 Visit(decls->at(i)); | |
70 CHECK_BAILOUT; | |
71 } | |
72 } | |
73 | |
74 | |
75 void FullCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) { | |
76 for (int i = 0, len = stmts->length(); i < len; i++) { | |
77 Visit(stmts->at(i)); | |
78 CHECK_BAILOUT; | |
79 } | |
80 } | |
81 | |
82 | |
83 void FullCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) { | |
84 Property* prop = decl->proxy()->AsProperty(); | |
85 if (prop != NULL) { | |
86 Visit(prop->obj()); | |
87 Visit(prop->key()); | |
88 } | |
89 | |
90 if (decl->fun() != NULL) { | |
91 Visit(decl->fun()); | |
92 } | |
93 } | |
94 | |
95 | |
96 void FullCodeGenSyntaxChecker::VisitBlock(Block* stmt) { | |
97 VisitStatements(stmt->statements()); | |
98 } | |
99 | |
100 | |
101 void FullCodeGenSyntaxChecker::VisitExpressionStatement( | |
102 ExpressionStatement* stmt) { | |
103 Visit(stmt->expression()); | |
104 } | |
105 | |
106 | |
107 void FullCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) { | |
108 // Supported. | |
109 } | |
110 | |
111 | |
112 void FullCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) { | |
113 Visit(stmt->condition()); | |
114 CHECK_BAILOUT; | |
115 Visit(stmt->then_statement()); | |
116 CHECK_BAILOUT; | |
117 Visit(stmt->else_statement()); | |
118 } | |
119 | |
120 | |
121 void FullCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) { | |
122 // Supported. | |
123 } | |
124 | |
125 | |
126 void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) { | |
127 // Supported. | |
128 } | |
129 | |
130 | |
131 void FullCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) { | |
132 Visit(stmt->expression()); | |
133 } | |
134 | |
135 | |
136 void FullCodeGenSyntaxChecker::VisitWithEnterStatement( | |
137 WithEnterStatement* stmt) { | |
138 Visit(stmt->expression()); | |
139 } | |
140 | |
141 | |
142 void FullCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) { | |
143 // Supported. | |
144 } | |
145 | |
146 | |
147 void FullCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) { | |
148 BAILOUT("SwitchStatement"); | |
149 } | |
150 | |
151 | |
152 void FullCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { | |
153 Visit(stmt->cond()); | |
154 CHECK_BAILOUT; | |
155 Visit(stmt->body()); | |
156 } | |
157 | |
158 | |
159 void FullCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) { | |
160 Visit(stmt->cond()); | |
161 CHECK_BAILOUT; | |
162 Visit(stmt->body()); | |
163 } | |
164 | |
165 | |
166 void FullCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) { | |
167 if (!FLAG_always_full_compiler) BAILOUT("ForStatement"); | |
168 if (stmt->init() != NULL) { | |
169 Visit(stmt->init()); | |
170 CHECK_BAILOUT; | |
171 } | |
172 if (stmt->cond() != NULL) { | |
173 Visit(stmt->cond()); | |
174 CHECK_BAILOUT; | |
175 } | |
176 Visit(stmt->body()); | |
177 if (stmt->next() != NULL) { | |
178 CHECK_BAILOUT; | |
179 Visit(stmt->next()); | |
180 } | |
181 } | |
182 | |
183 | |
184 void FullCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) { | |
185 BAILOUT("ForInStatement"); | |
186 } | |
187 | |
188 | |
189 void FullCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) { | |
190 Visit(stmt->try_block()); | |
191 CHECK_BAILOUT; | |
192 Visit(stmt->catch_block()); | |
193 } | |
194 | |
195 | |
196 void FullCodeGenSyntaxChecker::VisitTryFinallyStatement( | |
197 TryFinallyStatement* stmt) { | |
198 Visit(stmt->try_block()); | |
199 CHECK_BAILOUT; | |
200 Visit(stmt->finally_block()); | |
201 } | |
202 | |
203 | |
204 void FullCodeGenSyntaxChecker::VisitDebuggerStatement( | |
205 DebuggerStatement* stmt) { | |
206 // Supported. | |
207 } | |
208 | |
209 | |
210 void FullCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) { | |
211 // Supported. | |
212 } | |
213 | |
214 | |
215 void FullCodeGenSyntaxChecker::VisitSharedFunctionInfoLiteral( | |
216 SharedFunctionInfoLiteral* expr) { | |
217 BAILOUT("SharedFunctionInfoLiteral"); | |
218 } | |
219 | |
220 | |
221 void FullCodeGenSyntaxChecker::VisitConditional(Conditional* expr) { | |
222 Visit(expr->condition()); | |
223 CHECK_BAILOUT; | |
224 Visit(expr->then_expression()); | |
225 CHECK_BAILOUT; | |
226 Visit(expr->else_expression()); | |
227 } | |
228 | |
229 | |
230 void FullCodeGenSyntaxChecker::VisitSlot(Slot* expr) { | |
231 UNREACHABLE(); | |
232 } | |
233 | |
234 | |
235 void FullCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { | |
236 // Supported. | |
237 } | |
238 | |
239 | |
240 void FullCodeGenSyntaxChecker::VisitLiteral(Literal* expr) { | |
241 // Supported. | |
242 } | |
243 | |
244 | |
245 void FullCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) { | |
246 // Supported. | |
247 } | |
248 | |
249 | |
250 void FullCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) { | |
251 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | |
252 | |
253 for (int i = 0, len = properties->length(); i < len; i++) { | |
254 ObjectLiteral::Property* property = properties->at(i); | |
255 if (property->IsCompileTimeValue()) continue; | |
256 Visit(property->key()); | |
257 CHECK_BAILOUT; | |
258 Visit(property->value()); | |
259 CHECK_BAILOUT; | |
260 } | |
261 } | |
262 | |
263 | |
264 void FullCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) { | |
265 ZoneList<Expression*>* subexprs = expr->values(); | |
266 for (int i = 0, len = subexprs->length(); i < len; i++) { | |
267 Expression* subexpr = subexprs->at(i); | |
268 if (subexpr->AsLiteral() != NULL) continue; | |
269 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | |
270 Visit(subexpr); | |
271 CHECK_BAILOUT; | |
272 } | |
273 } | |
274 | |
275 | |
276 void FullCodeGenSyntaxChecker::VisitCatchExtensionObject( | |
277 CatchExtensionObject* expr) { | |
278 Visit(expr->key()); | |
279 CHECK_BAILOUT; | |
280 Visit(expr->value()); | |
281 } | |
282 | |
283 | |
284 void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) { | |
285 Token::Value op = expr->op(); | |
286 if (op == Token::INIT_CONST) BAILOUT("initialize constant"); | |
287 | |
288 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | |
289 Property* prop = expr->target()->AsProperty(); | |
290 ASSERT(var == NULL || prop == NULL); | |
291 if (var != NULL) { | |
292 if (var->mode() == Variable::CONST) BAILOUT("Assignment to const"); | |
293 // All other variables are supported. | |
294 } else if (prop != NULL) { | |
295 Visit(prop->obj()); | |
296 CHECK_BAILOUT; | |
297 Visit(prop->key()); | |
298 CHECK_BAILOUT; | |
299 } else { | |
300 // This is a throw reference error. | |
301 BAILOUT("non-variable/non-property assignment"); | |
302 } | |
303 | |
304 Visit(expr->value()); | |
305 } | |
306 | |
307 | |
308 void FullCodeGenSyntaxChecker::VisitThrow(Throw* expr) { | |
309 Visit(expr->exception()); | |
310 } | |
311 | |
312 | |
313 void FullCodeGenSyntaxChecker::VisitProperty(Property* expr) { | |
314 Visit(expr->obj()); | |
315 CHECK_BAILOUT; | |
316 Visit(expr->key()); | |
317 } | |
318 | |
319 | |
320 void FullCodeGenSyntaxChecker::VisitCall(Call* expr) { | |
321 Expression* fun = expr->expression(); | |
322 ZoneList<Expression*>* args = expr->arguments(); | |
323 Variable* var = fun->AsVariableProxy()->AsVariable(); | |
324 | |
325 // Check for supported calls | |
326 if (var != NULL && var->is_possibly_eval()) { | |
327 BAILOUT("call to the identifier 'eval'"); | |
328 } else if (var != NULL && !var->is_this() && var->is_global()) { | |
329 // Calls to global variables are supported. | |
330 } else if (var != NULL && var->slot() != NULL && | |
331 var->slot()->type() == Slot::LOOKUP) { | |
332 BAILOUT("call to a lookup slot"); | |
333 } else if (fun->AsProperty() != NULL) { | |
334 Property* prop = fun->AsProperty(); | |
335 Visit(prop->obj()); | |
336 CHECK_BAILOUT; | |
337 Visit(prop->key()); | |
338 CHECK_BAILOUT; | |
339 } else { | |
340 // Otherwise the call is supported if the function expression is. | |
341 Visit(fun); | |
342 } | |
343 // Check all arguments to the call. | |
344 for (int i = 0; i < args->length(); i++) { | |
345 Visit(args->at(i)); | |
346 CHECK_BAILOUT; | |
347 } | |
348 } | |
349 | |
350 | |
351 void FullCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { | |
352 Visit(expr->expression()); | |
353 CHECK_BAILOUT; | |
354 ZoneList<Expression*>* args = expr->arguments(); | |
355 // Check all arguments to the call | |
356 for (int i = 0; i < args->length(); i++) { | |
357 Visit(args->at(i)); | |
358 CHECK_BAILOUT; | |
359 } | |
360 } | |
361 | |
362 | |
363 void FullCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { | |
364 // Check for inline runtime call | |
365 if (expr->name()->Get(0) == '_' && | |
366 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { | |
367 BAILOUT("inlined runtime call"); | |
368 } | |
369 // Check all arguments to the call. (Relies on TEMP meaning STACK.) | |
370 for (int i = 0; i < expr->arguments()->length(); i++) { | |
371 Visit(expr->arguments()->at(i)); | |
372 CHECK_BAILOUT; | |
373 } | |
374 } | |
375 | |
376 | |
377 void FullCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { | |
378 switch (expr->op()) { | |
379 case Token::ADD: | |
380 case Token::BIT_NOT: | |
381 case Token::NOT: | |
382 case Token::SUB: | |
383 case Token::TYPEOF: | |
384 case Token::VOID: | |
385 Visit(expr->expression()); | |
386 break; | |
387 case Token::DELETE: | |
388 BAILOUT("UnaryOperation: DELETE"); | |
389 default: | |
390 UNREACHABLE(); | |
391 } | |
392 } | |
393 | |
394 | |
395 void FullCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { | |
396 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | |
397 Property* prop = expr->expression()->AsProperty(); | |
398 ASSERT(var == NULL || prop == NULL); | |
399 if (var != NULL) { | |
400 // All global variables are supported. | |
401 if (!var->is_global()) { | |
402 ASSERT(var->slot() != NULL); | |
403 Slot::Type type = var->slot()->type(); | |
404 if (type == Slot::LOOKUP) { | |
405 BAILOUT("CountOperation with lookup slot"); | |
406 } | |
407 } | |
408 } else if (prop != NULL) { | |
409 Visit(prop->obj()); | |
410 CHECK_BAILOUT; | |
411 Visit(prop->key()); | |
412 CHECK_BAILOUT; | |
413 } else { | |
414 // This is a throw reference error. | |
415 BAILOUT("CountOperation non-variable/non-property expression"); | |
416 } | |
417 } | |
418 | |
419 | |
420 void FullCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { | |
421 Visit(expr->left()); | |
422 CHECK_BAILOUT; | |
423 Visit(expr->right()); | |
424 } | |
425 | |
426 | |
427 void FullCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { | |
428 Visit(expr->left()); | |
429 CHECK_BAILOUT; | |
430 Visit(expr->right()); | |
431 } | |
432 | |
433 | |
434 void FullCodeGenSyntaxChecker::VisitCompareToNull(CompareToNull* expr) { | |
435 Visit(expr->expression()); | |
436 } | |
437 | |
438 | |
439 void FullCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { | |
440 // Supported. | |
441 } | |
442 | |
443 #undef BAILOUT | |
444 #undef CHECK_BAILOUT | |
445 | |
446 | |
447 void BreakableStatementChecker::Check(Statement* stmt) { | 41 void BreakableStatementChecker::Check(Statement* stmt) { |
448 Visit(stmt); | 42 Visit(stmt); |
449 } | 43 } |
450 | 44 |
451 | 45 |
452 void BreakableStatementChecker::Check(Expression* expr) { | 46 void BreakableStatementChecker::Check(Expression* expr) { |
453 Visit(expr); | 47 Visit(expr); |
454 } | 48 } |
455 | 49 |
456 | 50 |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 | 455 |
862 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { | 456 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { |
863 Handle<String> name = expr->name(); | 457 Handle<String> name = expr->name(); |
864 SmartPointer<char> cstring = name->ToCString(); | 458 SmartPointer<char> cstring = name->ToCString(); |
865 | 459 |
866 #define CHECK_EMIT_INLINE_CALL(name, x, y) \ | 460 #define CHECK_EMIT_INLINE_CALL(name, x, y) \ |
867 if (strcmp("_"#name, *cstring) == 0) { \ | 461 if (strcmp("_"#name, *cstring) == 0) { \ |
868 Emit##name(expr->arguments()); \ | 462 Emit##name(expr->arguments()); \ |
869 return; \ | 463 return; \ |
870 } | 464 } |
871 | |
872 INLINE_RUNTIME_FUNCTION_LIST(CHECK_EMIT_INLINE_CALL) | 465 INLINE_RUNTIME_FUNCTION_LIST(CHECK_EMIT_INLINE_CALL) |
| 466 #undef CHECK_EMIT_INLINE_CALL |
873 UNREACHABLE(); | 467 UNREACHABLE(); |
874 #undef CHECK_EMIT_INLINE_CALL | |
875 } | 468 } |
876 | 469 |
877 | 470 |
878 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 471 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
879 Comment cmnt(masm_, "[ BinaryOperation"); | 472 Comment cmnt(masm_, "[ BinaryOperation"); |
880 switch (expr->op()) { | 473 switch (expr->op()) { |
881 case Token::COMMA: | 474 case Token::COMMA: |
882 VisitForEffect(expr->left()); | 475 VisitForEffect(expr->left()); |
883 Visit(expr->right()); | 476 Visit(expr->right()); |
884 break; | 477 break; |
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1442 ASSERT(args->length() == 1); | 1035 ASSERT(args->length() == 1); |
1443 VisitForValue(args->at(0), kStack); | 1036 VisitForValue(args->at(0), kStack); |
1444 __ CallRuntime(Runtime::kRegExpCloneResult, 1); | 1037 __ CallRuntime(Runtime::kRegExpCloneResult, 1); |
1445 Apply(context_, result_register()); | 1038 Apply(context_, result_register()); |
1446 } | 1039 } |
1447 | 1040 |
1448 #undef __ | 1041 #undef __ |
1449 | 1042 |
1450 | 1043 |
1451 } } // namespace v8::internal | 1044 } } // namespace v8::internal |
OLD | NEW |