Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2106 // TODO(kasperl): Try to improve the way we compute the last added | 2106 // TODO(kasperl): Try to improve the way we compute the last added |
| 2107 // instruction. The NULL check makes me uncomfortable. | 2107 // instruction. The NULL check makes me uncomfortable. |
| 2108 HValue* last = subgraph()->exit_block()->GetLastInstruction(); | 2108 HValue* last = subgraph()->exit_block()->GetLastInstruction(); |
| 2109 if (last != NULL && last->HasSideEffects()) { | 2109 if (last != NULL && last->HasSideEffects()) { |
| 2110 AddSimulate(expr->id()); | 2110 AddSimulate(expr->id()); |
| 2111 } | 2111 } |
| 2112 ASSERT(environment()->values()->length() == original_height + 1); | 2112 ASSERT(environment()->values()->length() == original_height + 1); |
| 2113 } | 2113 } |
| 2114 | 2114 |
| 2115 | 2115 |
| 2116 void HGraphBuilder::VisitForTypeofValue(Expression* expr) { | |
|
Kevin Millikin (Chromium)
2010/12/09 13:16:51
It seems to me that "parent is typeof" is just a f
fschneider
2010/12/22 16:02:34
Done.
| |
| 2117 VariableProxy* proxy = expr->AsVariableProxy(); | |
| 2118 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | |
|
Kevin Millikin (Chromium)
2010/12/09 13:16:51
I think you can just ask the proxy is_this (and ma
fschneider
2010/12/22 16:02:34
Done. This part of the code is now gone.
| |
| 2119 #ifdef DEBUG | |
| 2120 int original_height = environment()->values()->length(); | |
| 2121 #endif | |
| 2122 HandleGlobalVariableLoad(proxy, true); // Inside typeof. | |
| 2123 // Generic global loads always have a side effect. | |
| 2124 AddSimulate(expr->id()); | |
| 2125 ASSERT(environment()->values()->length() == original_height + 1); | |
| 2126 } else { | |
| 2127 VisitForValue(expr); | |
| 2128 } | |
| 2129 } | |
| 2130 | |
| 2131 | |
| 2116 HValue* HGraphBuilder::VisitArgument(Expression* expr) { | 2132 HValue* HGraphBuilder::VisitArgument(Expression* expr) { |
| 2117 VisitForValue(expr); | 2133 VisitForValue(expr); |
| 2118 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; | 2134 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; |
| 2119 return environment()->Top(); | 2135 return environment()->Top(); |
| 2120 } | 2136 } |
| 2121 | 2137 |
| 2122 | 2138 |
| 2123 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { | 2139 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { |
| 2124 for (int i = 0; i < arguments->length(); i++) { | 2140 for (int i = 0; i < arguments->length(); i++) { |
| 2125 VisitArgument(arguments->at(i)); | 2141 VisitArgument(arguments->at(i)); |
| (...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2931 then_graph->entry_block(), | 2947 then_graph->entry_block(), |
| 2932 else_graph->entry_block(), | 2948 else_graph->entry_block(), |
| 2933 false, false); | 2949 false, false); |
| 2934 if (HasStackOverflow()) return; | 2950 if (HasStackOverflow()) return; |
| 2935 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); | 2951 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); |
| 2936 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); | 2952 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); |
| 2937 current_subgraph_->AppendJoin(then_graph, else_graph, expr); | 2953 current_subgraph_->AppendJoin(then_graph, else_graph, expr); |
| 2938 } | 2954 } |
| 2939 | 2955 |
| 2940 | 2956 |
| 2941 void HGraphBuilder::LookupGlobalPropertyCell(VariableProxy* expr, | 2957 void HGraphBuilder::LookupGlobalPropertyCell(VariableProxy* expr, |
|
Kevin Millikin (Chromium)
2010/12/09 13:16:51
It seems like it would be cleaner for this functio
fschneider
2010/12/22 16:02:34
I wanted to be able to use the BAILOUT macro from
| |
| 2942 LookupResult* lookup, | 2958 LookupResult* lookup, |
| 2943 bool is_store) { | 2959 bool is_store, |
| 2960 bool* is_generic) { | |
| 2961 *is_generic = true; | |
| 2944 if (expr->is_this()) { | 2962 if (expr->is_this()) { |
| 2945 BAILOUT("global this reference"); | 2963 BAILOUT("global this reference"); |
| 2946 } | 2964 } |
| 2947 if (!graph()->info()->has_global_object()) { | 2965 if (!graph()->info()->has_global_object()) { |
| 2948 BAILOUT("no global object to optimize VariableProxy"); | 2966 BAILOUT("no global object to optimize VariableProxy"); |
| 2949 } | 2967 } |
| 2950 Handle<GlobalObject> global(graph()->info()->global_object()); | 2968 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 2951 global->Lookup(*expr->name(), lookup); | 2969 global->Lookup(*expr->name(), lookup); |
| 2952 if (!lookup->IsProperty()) { | 2970 if (!lookup->IsProperty()) return; |
| 2953 BAILOUT("global variable cell not yet introduced"); | 2971 if (lookup->type() != NORMAL) return; |
| 2972 if (is_store && lookup->IsReadOnly()) { | |
| 2973 BAILOUT("store to read-only global variable"); | |
| 2954 } | 2974 } |
| 2955 if (lookup->type() != NORMAL) { | 2975 *is_generic = false; |
| 2956 BAILOUT("global variable has accessors"); | 2976 } |
| 2957 } | 2977 |
| 2958 if (is_store && lookup->IsReadOnly()) { | 2978 |
| 2959 BAILOUT("read-only global variable"); | 2979 void HGraphBuilder::HandleGlobalVariableLoad(VariableProxy* expr, |
|
Kevin Millikin (Chromium)
2010/12/09 13:16:51
We need to restore some sanity to these helper fun
fschneider
2010/12/22 16:02:34
Done.
| |
| 2980 bool inside_typeof) { | |
| 2981 LookupResult lookup; | |
| 2982 bool is_generic = true; | |
| 2983 LookupGlobalPropertyCell(expr, &lookup, false, &is_generic); | |
| 2984 CHECK_BAILOUT; | |
| 2985 | |
| 2986 Handle<GlobalObject> global(graph()->info()->global_object()); | |
| 2987 if (is_generic || global->IsAccessCheckNeeded()) { | |
| 2988 PushAndAdd(new HLoadGlobalGeneric(expr->var()->name(), inside_typeof)); | |
|
Kevin Millikin (Chromium)
2010/12/09 13:16:51
Here you could just ask the ast_context if it is a
fschneider
2010/12/22 16:02:34
Done.
| |
| 2989 } else { | |
| 2990 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | |
| 2991 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | |
| 2992 PushAndAdd(new HLoadGlobal(cell, check_hole)); | |
| 2960 } | 2993 } |
| 2961 } | 2994 } |
| 2962 | 2995 |
| 2963 | 2996 |
| 2964 void HGraphBuilder::HandleGlobalVariableLoad(VariableProxy* expr) { | |
| 2965 LookupResult lookup; | |
| 2966 LookupGlobalPropertyCell(expr, &lookup, false); | |
| 2967 CHECK_BAILOUT; | |
| 2968 | |
| 2969 Handle<GlobalObject> global(graph()->info()->global_object()); | |
| 2970 // TODO(3039103): Handle global property load through an IC call when access | |
| 2971 // checks are enabled. | |
| 2972 if (global->IsAccessCheckNeeded()) { | |
| 2973 BAILOUT("global object requires access check"); | |
| 2974 } | |
| 2975 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | |
| 2976 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | |
| 2977 PushAndAdd(new HLoadGlobal(cell, check_hole)); | |
| 2978 } | |
| 2979 | |
| 2980 | |
| 2981 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 2997 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 2982 Variable* variable = expr->AsVariable(); | 2998 Variable* variable = expr->AsVariable(); |
| 2983 if (variable == NULL) { | 2999 if (variable == NULL) { |
| 2984 BAILOUT("reference to rewritten variable"); | 3000 BAILOUT("reference to rewritten variable"); |
| 2985 } else if (variable->IsStackAllocated()) { | 3001 } else if (variable->IsStackAllocated()) { |
| 2986 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { | 3002 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { |
| 2987 BAILOUT("unsupported context for arguments object"); | 3003 BAILOUT("unsupported context for arguments object"); |
| 2988 } | 3004 } |
| 2989 Push(environment()->Lookup(variable)); | 3005 Push(environment()->Lookup(variable)); |
| 2990 } else if (variable->is_global()) { | 3006 } else if (variable->is_global()) { |
| 2991 HandleGlobalVariableLoad(expr); | 3007 HandleGlobalVariableLoad(expr, false); // Not inside typeof. |
| 2992 } else { | 3008 } else { |
| 2993 BAILOUT("reference to non-stack-allocated/non-global variable"); | 3009 BAILOUT("reference to non-stack-allocated/non-global variable"); |
| 2994 } | 3010 } |
| 2995 } | 3011 } |
| 2996 | 3012 |
| 2997 | 3013 |
| 2998 void HGraphBuilder::VisitLiteral(Literal* expr) { | 3014 void HGraphBuilder::VisitLiteral(Literal* expr) { |
| 2999 PushAndAdd(new HConstant(expr->handle(), Representation::Tagged())); | 3015 PushAndAdd(new HConstant(expr->handle(), Representation::Tagged())); |
| 3000 } | 3016 } |
| 3001 | 3017 |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3333 Push(value); | 3349 Push(value); |
| 3334 instr->set_position(expr->position()); | 3350 instr->set_position(expr->position()); |
| 3335 AddInstruction(instr); | 3351 AddInstruction(instr); |
| 3336 } | 3352 } |
| 3337 | 3353 |
| 3338 | 3354 |
| 3339 void HGraphBuilder::HandleGlobalVariableAssignment(VariableProxy* proxy, | 3355 void HGraphBuilder::HandleGlobalVariableAssignment(VariableProxy* proxy, |
| 3340 HValue* value, | 3356 HValue* value, |
| 3341 int position) { | 3357 int position) { |
| 3342 LookupResult lookup; | 3358 LookupResult lookup; |
| 3343 LookupGlobalPropertyCell(proxy, &lookup, true); | 3359 bool is_generic; |
| 3360 LookupGlobalPropertyCell(proxy, &lookup, true, &is_generic); | |
| 3344 CHECK_BAILOUT; | 3361 CHECK_BAILOUT; |
| 3345 | 3362 |
| 3346 Handle<GlobalObject> global(graph()->info()->global_object()); | 3363 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 3347 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3364 if (!is_generic && !global->IsAccessCheckNeeded()) { |
| 3348 HInstruction* instr = new HStoreGlobal(value, cell); | 3365 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 3349 instr->set_position(position); | 3366 HInstruction* instr = new HStoreGlobal(value, cell); |
| 3350 AddInstruction(instr); | 3367 instr->set_position(position); |
| 3368 AddInstruction(instr); | |
| 3369 } else { | |
| 3370 BAILOUT("unsupported store to global"); | |
| 3371 } | |
| 3351 } | 3372 } |
| 3352 | 3373 |
| 3353 | 3374 |
| 3354 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 3375 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 3355 Expression* target = expr->target(); | 3376 Expression* target = expr->target(); |
| 3356 VariableProxy* proxy = target->AsVariableProxy(); | 3377 VariableProxy* proxy = target->AsVariableProxy(); |
| 3357 Variable* var = proxy->AsVariable(); | 3378 Variable* var = proxy->AsVariable(); |
| 3358 Property* prop = target->AsProperty(); | 3379 Property* prop = target->AsProperty(); |
| 3359 ASSERT(var == NULL || prop == NULL); | 3380 ASSERT(var == NULL || prop == NULL); |
| 3360 | 3381 |
| (...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4393 break; | 4414 break; |
| 4394 case Token::SUB: | 4415 case Token::SUB: |
| 4395 instr = new HMul(graph_->GetConstantMinus1(), value); | 4416 instr = new HMul(graph_->GetConstantMinus1(), value); |
| 4396 break; | 4417 break; |
| 4397 default: | 4418 default: |
| 4398 UNREACHABLE(); | 4419 UNREACHABLE(); |
| 4399 break; | 4420 break; |
| 4400 } | 4421 } |
| 4401 PushAndAdd(instr); | 4422 PushAndAdd(instr); |
| 4402 } else if (op == Token::TYPEOF) { | 4423 } else if (op == Token::TYPEOF) { |
| 4403 VISIT_FOR_VALUE(expr->expression()); | 4424 VisitForTypeofValue(expr->expression()); |
| 4425 if (HasStackOverflow()) return; | |
| 4404 HValue* value = Pop(); | 4426 HValue* value = Pop(); |
| 4405 PushAndAdd(new HTypeof(value)); | 4427 PushAndAdd(new HTypeof(value)); |
| 4406 } else { | 4428 } else { |
| 4407 BAILOUT("Value: unsupported unary operation"); | 4429 BAILOUT("Value: unsupported unary operation"); |
| 4408 } | 4430 } |
| 4409 } | 4431 } |
| 4410 | 4432 |
| 4411 | 4433 |
| 4412 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { | 4434 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { |
| 4413 // IncrementOperation is never visited by the visitor. It only | 4435 // IncrementOperation is never visited by the visitor. It only |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4694 PushAndAdd(instr, expr->position()); | 4716 PushAndAdd(instr, expr->position()); |
| 4695 return; | 4717 return; |
| 4696 } | 4718 } |
| 4697 | 4719 |
| 4698 // Check for the pattern: typeof <expression> == <string literal>. | 4720 // Check for the pattern: typeof <expression> == <string literal>. |
| 4699 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); | 4721 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); |
| 4700 Literal* right_literal = expr->right()->AsLiteral(); | 4722 Literal* right_literal = expr->right()->AsLiteral(); |
| 4701 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && | 4723 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
| 4702 left_unary != NULL && left_unary->op() == Token::TYPEOF && | 4724 left_unary != NULL && left_unary->op() == Token::TYPEOF && |
| 4703 right_literal != NULL && right_literal->handle()->IsString()) { | 4725 right_literal != NULL && right_literal->handle()->IsString()) { |
| 4704 VISIT_FOR_VALUE(left_unary->expression()); | 4726 VisitForTypeofValue(left_unary->expression()); |
| 4727 if (HasStackOverflow()) return; | |
| 4705 HValue* left = Pop(); | 4728 HValue* left = Pop(); |
| 4706 HInstruction* instr = new HTypeofIs(left, | 4729 HInstruction* instr = new HTypeofIs(left, |
| 4707 Handle<String>::cast(right_literal->handle())); | 4730 Handle<String>::cast(right_literal->handle())); |
| 4708 PushAndAdd(instr, expr->position()); | 4731 PushAndAdd(instr, expr->position()); |
| 4709 return; | 4732 return; |
| 4710 } | 4733 } |
| 4711 | 4734 |
| 4712 VISIT_FOR_VALUE(expr->left()); | 4735 VISIT_FOR_VALUE(expr->left()); |
| 4713 VISIT_FOR_VALUE(expr->right()); | 4736 VISIT_FOR_VALUE(expr->right()); |
| 4714 | 4737 |
| (...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5541 } | 5564 } |
| 5542 | 5565 |
| 5543 #ifdef DEBUG | 5566 #ifdef DEBUG |
| 5544 if (graph_ != NULL) graph_->Verify(); | 5567 if (graph_ != NULL) graph_->Verify(); |
| 5545 if (chunk_ != NULL) chunk_->Verify(); | 5568 if (chunk_ != NULL) chunk_->Verify(); |
| 5546 if (allocator_ != NULL) allocator_->Verify(); | 5569 if (allocator_ != NULL) allocator_->Verify(); |
| 5547 #endif | 5570 #endif |
| 5548 } | 5571 } |
| 5549 | 5572 |
| 5550 } } // namespace v8::internal | 5573 } } // namespace v8::internal |
| OLD | NEW |