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 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 HConstant* HGraph::GetConstantTrue() { | 495 HConstant* HGraph::GetConstantTrue() { |
496 return GetConstant(&constant_true_, Heap::true_value()); | 496 return GetConstant(&constant_true_, Heap::true_value()); |
497 } | 497 } |
498 | 498 |
499 | 499 |
500 HConstant* HGraph::GetConstantFalse() { | 500 HConstant* HGraph::GetConstantFalse() { |
501 return GetConstant(&constant_false_, Heap::false_value()); | 501 return GetConstant(&constant_false_, Heap::false_value()); |
502 } | 502 } |
503 | 503 |
504 | 504 |
505 HConstant* HGraph::GetConstantHole() { | |
506 return GetConstant(&constant_hole_, Heap::the_hole_value()); | |
507 } | |
508 | |
509 | |
505 void HSubgraph::AppendOptional(HSubgraph* graph, | 510 void HSubgraph::AppendOptional(HSubgraph* graph, |
506 bool on_true_branch, | 511 bool on_true_branch, |
507 HValue* boolean_value) { | 512 HValue* boolean_value) { |
508 ASSERT(HasExit() && graph->HasExit()); | 513 ASSERT(HasExit() && graph->HasExit()); |
509 HBasicBlock* other_block = graph_->CreateBasicBlock(); | 514 HBasicBlock* other_block = graph_->CreateBasicBlock(); |
510 HBasicBlock* join_block = graph_->CreateBasicBlock(); | 515 HBasicBlock* join_block = graph_->CreateBasicBlock(); |
511 | 516 |
512 HBasicBlock* true_branch = other_block; | 517 HBasicBlock* true_branch = other_block; |
513 HBasicBlock* false_branch = graph->entry_block(); | 518 HBasicBlock* false_branch = graph->entry_block(); |
514 if (on_true_branch) { | 519 if (on_true_branch) { |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
884 | 889 |
885 bool HGraph::CollectPhis() { | 890 bool HGraph::CollectPhis() { |
886 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); | 891 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
887 phi_list_ = new ZoneList<HPhi*>(blocks->length()); | 892 phi_list_ = new ZoneList<HPhi*>(blocks->length()); |
888 for (int i = 0; i < blocks->length(); ++i) { | 893 for (int i = 0; i < blocks->length(); ++i) { |
889 for (int j = 0; j < blocks->at(i)->phis()->length(); j++) { | 894 for (int j = 0; j < blocks->at(i)->phis()->length(); j++) { |
890 HPhi* phi = blocks->at(i)->phis()->at(j); | 895 HPhi* phi = blocks->at(i)->phis()->at(j); |
891 phi_list_->Add(phi); | 896 phi_list_->Add(phi); |
892 // We don't support phi uses of arguments for now. | 897 // We don't support phi uses of arguments for now. |
893 if (phi->CheckFlag(HValue::kIsArguments)) return false; | 898 if (phi->CheckFlag(HValue::kIsArguments)) return false; |
899 // Check for the hole value (from an uninitialized const). | |
900 for (int k = 0; k < phi->OperandCount(); k++) { | |
901 if (phi->OperandAt(k) == GetConstantHole()) return false; | |
902 } | |
894 } | 903 } |
895 } | 904 } |
896 return true; | 905 return true; |
897 } | 906 } |
898 | 907 |
899 | 908 |
900 void HGraph::InferTypes(ZoneList<HValue*>* worklist) { | 909 void HGraph::InferTypes(ZoneList<HValue*>* worklist) { |
901 BitVector in_worklist(GetMaximumValueID()); | 910 BitVector in_worklist(GetMaximumValueID()); |
902 for (int i = 0; i < worklist->length(); ++i) { | 911 for (int i = 0; i < worklist->length(); ++i) { |
903 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); | 912 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); |
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2213 | 2222 |
2214 if (graph_->HasExit()) { | 2223 if (graph_->HasExit()) { |
2215 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); | 2224 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); |
2216 } | 2225 } |
2217 } | 2226 } |
2218 | 2227 |
2219 graph_->OrderBlocks(); | 2228 graph_->OrderBlocks(); |
2220 graph_->AssignDominators(); | 2229 graph_->AssignDominators(); |
2221 graph_->EliminateRedundantPhis(); | 2230 graph_->EliminateRedundantPhis(); |
2222 if (!graph_->CollectPhis()) { | 2231 if (!graph_->CollectPhis()) { |
2223 Bailout("Phi-use of arguments object"); | 2232 Bailout("Unsupported phi-use"); |
2224 return NULL; | 2233 return NULL; |
2225 } | 2234 } |
2226 | 2235 |
2227 HInferRepresentation rep(graph_); | 2236 HInferRepresentation rep(graph_); |
2228 rep.Analyze(); | 2237 rep.Analyze(); |
2229 | 2238 |
2230 if (FLAG_use_range) { | 2239 if (FLAG_use_range) { |
2231 HRangeAnalysis rangeAnalysis(graph_); | 2240 HRangeAnalysis rangeAnalysis(graph_); |
2232 rangeAnalysis.Analyze(); | 2241 rangeAnalysis.Analyze(); |
2233 } | 2242 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2322 } | 2331 } |
2323 | 2332 |
2324 | 2333 |
2325 void HGraphBuilder::SetupScope(Scope* scope) { | 2334 void HGraphBuilder::SetupScope(Scope* scope) { |
2326 // We don't yet handle the function name for named function expressions. | 2335 // We don't yet handle the function name for named function expressions. |
2327 if (scope->function() != NULL) BAILOUT("named function expression"); | 2336 if (scope->function() != NULL) BAILOUT("named function expression"); |
2328 | 2337 |
2329 // We can't handle heap-allocated locals. | 2338 // We can't handle heap-allocated locals. |
2330 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); | 2339 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); |
2331 | 2340 |
2341 if (scope->HasIllegalRedeclaration()) BAILOUT("illegal redeclaration"); | |
2342 | |
2332 HConstant* undefined_constant = | 2343 HConstant* undefined_constant = |
2333 new HConstant(Factory::undefined_value(), Representation::Tagged()); | 2344 new HConstant(Factory::undefined_value(), Representation::Tagged()); |
2334 AddInstruction(undefined_constant); | 2345 AddInstruction(undefined_constant); |
2335 graph_->set_undefined_constant(undefined_constant); | 2346 graph_->set_undefined_constant(undefined_constant); |
2336 | 2347 |
2337 // Set the initial values of parameters including "this". "This" has | 2348 // Set the initial values of parameters including "this". "This" has |
2338 // parameter index 0. | 2349 // parameter index 0. |
2339 int count = scope->num_parameters() + 1; | 2350 int count = scope->num_parameters() + 1; |
2340 for (int i = 0; i < count; ++i) { | 2351 for (int i = 0; i < count; ++i) { |
2341 HInstruction* parameter = AddInstruction(new HParameter(i)); | 2352 HInstruction* parameter = AddInstruction(new HParameter(i)); |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2929 BAILOUT("read-only global variable"); | 2940 BAILOUT("read-only global variable"); |
2930 } | 2941 } |
2931 } | 2942 } |
2932 | 2943 |
2933 | 2944 |
2934 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 2945 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
2935 Variable* variable = expr->AsVariable(); | 2946 Variable* variable = expr->AsVariable(); |
2936 if (variable == NULL) { | 2947 if (variable == NULL) { |
2937 BAILOUT("reference to rewritten variable"); | 2948 BAILOUT("reference to rewritten variable"); |
2938 } else if (variable->IsStackAllocated()) { | 2949 } else if (variable->IsStackAllocated()) { |
2939 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { | 2950 HValue* value = environment()->Lookup(variable); |
2951 if (value->CheckFlag(HValue::kIsArguments)) { | |
2940 BAILOUT("unsupported context for arguments object"); | 2952 BAILOUT("unsupported context for arguments object"); |
2941 } | 2953 } |
2942 ast_context()->ReturnValue(environment()->Lookup(variable)); | 2954 if (variable->mode() == Variable::CONST && |
2955 value == graph()->GetConstantHole()) { | |
2956 BAILOUT("unsupported reference to const variable"); | |
Kevin Millikin (Chromium)
2011/01/04 13:46:33
ast_context()->ReturnValue(graph()->GetConstantUnd
| |
2957 } | |
2958 ast_context()->ReturnValue(value); | |
2943 } else if (variable->is_global()) { | 2959 } else if (variable->is_global()) { |
2944 LookupResult lookup; | 2960 LookupResult lookup; |
2945 LookupGlobalPropertyCell(variable, &lookup, false); | 2961 LookupGlobalPropertyCell(variable, &lookup, false); |
2946 CHECK_BAILOUT; | 2962 CHECK_BAILOUT; |
2947 | 2963 |
2948 Handle<GlobalObject> global(graph()->info()->global_object()); | 2964 Handle<GlobalObject> global(graph()->info()->global_object()); |
2949 // TODO(3039103): Handle global property load through an IC call when access | 2965 // TODO(3039103): Handle global property load through an IC call when access |
2950 // checks are enabled. | 2966 // checks are enabled. |
2951 if (global->IsAccessCheckNeeded()) { | 2967 if (global->IsAccessCheckNeeded()) { |
2952 BAILOUT("global object requires access check"); | 2968 BAILOUT("global object requires access check"); |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3351 Variable* var = proxy->AsVariable(); | 3367 Variable* var = proxy->AsVariable(); |
3352 Property* prop = target->AsProperty(); | 3368 Property* prop = target->AsProperty(); |
3353 ASSERT(var == NULL || prop == NULL); | 3369 ASSERT(var == NULL || prop == NULL); |
3354 | 3370 |
3355 // We have a second position recorded in the FullCodeGenerator to have | 3371 // We have a second position recorded in the FullCodeGenerator to have |
3356 // type feedback for the binary operation. | 3372 // type feedback for the binary operation. |
3357 BinaryOperation* operation = expr->binary_operation(); | 3373 BinaryOperation* operation = expr->binary_operation(); |
3358 operation->RecordTypeFeedback(oracle()); | 3374 operation->RecordTypeFeedback(oracle()); |
3359 | 3375 |
3360 if (var != NULL) { | 3376 if (var != NULL) { |
3377 if (var->mode() == Variable::CONST) BAILOUT("unsupported const assignment"); | |
Kevin Millikin (Chromium)
2011/01/04 13:46:33
Instead of statically bailing out, how about visit
| |
3361 if (!var->is_global() && !var->IsStackAllocated()) { | 3378 if (!var->is_global() && !var->IsStackAllocated()) { |
3362 BAILOUT("non-stack/non-global in compound assignment"); | 3379 BAILOUT("non-stack/non-global in compound assignment"); |
3363 } | 3380 } |
3364 | 3381 |
3365 VISIT_FOR_VALUE(operation); | 3382 VISIT_FOR_VALUE(operation); |
3366 | 3383 |
3367 if (var->is_global()) { | 3384 if (var->is_global()) { |
3368 HandleGlobalVariableAssignment(var, | 3385 HandleGlobalVariableAssignment(var, |
3369 Top(), | 3386 Top(), |
3370 expr->position(), | 3387 expr->position(), |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3455 Variable* var = proxy->AsVariable(); | 3472 Variable* var = proxy->AsVariable(); |
3456 Property* prop = expr->target()->AsProperty(); | 3473 Property* prop = expr->target()->AsProperty(); |
3457 ASSERT(var == NULL || prop == NULL); | 3474 ASSERT(var == NULL || prop == NULL); |
3458 | 3475 |
3459 if (expr->is_compound()) { | 3476 if (expr->is_compound()) { |
3460 HandleCompoundAssignment(expr); | 3477 HandleCompoundAssignment(expr); |
3461 return; | 3478 return; |
3462 } | 3479 } |
3463 | 3480 |
3464 if (var != NULL) { | 3481 if (var != NULL) { |
3482 if (var->mode() == Variable::CONST) { | |
3483 if (expr->op() != Token::INIT_CONST) { | |
3484 BAILOUT("unsupported const assignment"); | |
Kevin Millikin (Chromium)
2011/01/04 13:46:33
Instead of statically bailing out for non-INIT_CON
| |
3485 } | |
3486 // We insert a use of the old value to detect unsupported uses of const | |
3487 // variables (e.g. initialization inside a loop). | |
3488 HValue* old_value = environment()->Lookup(var); | |
Kevin Millikin (Chromium)
2011/01/04 13:46:33
It's a little indirect to add this use and detect
| |
3489 AddInstruction(new HInitConst(old_value)); | |
3490 } | |
3491 | |
3492 | |
3465 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); | 3493 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); |
3466 | 3494 |
3467 // Handle the assignment. | 3495 // Handle the assignment. |
3468 if (var->is_global()) { | 3496 if (var->is_global()) { |
3469 VISIT_FOR_VALUE(expr->value()); | 3497 VISIT_FOR_VALUE(expr->value()); |
3470 HandleGlobalVariableAssignment(var, | 3498 HandleGlobalVariableAssignment(var, |
3471 Top(), | 3499 Top(), |
3472 expr->position(), | 3500 expr->position(), |
3473 expr->AssignmentId()); | 3501 expr->AssignmentId()); |
3474 } else { | 3502 } else { |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4527 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 4555 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
4528 IncrementOperation* increment = expr->increment(); | 4556 IncrementOperation* increment = expr->increment(); |
4529 Expression* target = increment->expression(); | 4557 Expression* target = increment->expression(); |
4530 VariableProxy* proxy = target->AsVariableProxy(); | 4558 VariableProxy* proxy = target->AsVariableProxy(); |
4531 Variable* var = proxy->AsVariable(); | 4559 Variable* var = proxy->AsVariable(); |
4532 Property* prop = target->AsProperty(); | 4560 Property* prop = target->AsProperty(); |
4533 ASSERT(var == NULL || prop == NULL); | 4561 ASSERT(var == NULL || prop == NULL); |
4534 bool inc = expr->op() == Token::INC; | 4562 bool inc = expr->op() == Token::INC; |
4535 | 4563 |
4536 if (var != NULL) { | 4564 if (var != NULL) { |
4565 if (var->mode() == Variable::CONST) BAILOUT("unsupported count operation"); | |
Kevin Millikin (Chromium)
2011/01/04 13:46:33
Same comment.
| |
4537 if (!var->is_global() && !var->IsStackAllocated()) { | 4566 if (!var->is_global() && !var->IsStackAllocated()) { |
4538 BAILOUT("non-stack/non-global variable in count operation"); | 4567 BAILOUT("non-stack/non-global variable in count operation"); |
4539 } | 4568 } |
4540 | 4569 |
4541 VISIT_FOR_VALUE(target); | 4570 VISIT_FOR_VALUE(target); |
4542 | 4571 |
4543 // Match the full code generator stack by simulating an extra stack | 4572 // Match the full code generator stack by simulating an extra stack |
4544 // element for postfix operations in a non-effect context. | 4573 // element for postfix operations in a non-effect context. |
4545 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | 4574 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); |
4546 HValue* before = has_extra ? Top() : Pop(); | 4575 HValue* before = has_extra ? Top() : Pop(); |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4881 | 4910 |
4882 | 4911 |
4883 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 4912 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
4884 BAILOUT("ThisFunction"); | 4913 BAILOUT("ThisFunction"); |
4885 } | 4914 } |
4886 | 4915 |
4887 | 4916 |
4888 void HGraphBuilder::VisitDeclaration(Declaration* decl) { | 4917 void HGraphBuilder::VisitDeclaration(Declaration* decl) { |
4889 // We allow only declarations that do not require code generation. | 4918 // We allow only declarations that do not require code generation. |
4890 // The following all require code generation: global variables and | 4919 // The following all require code generation: global variables and |
4891 // functions, variables with slot type LOOKUP, declarations with | 4920 // functions, variables with slot type LOOKUP |
Kevin Millikin (Chromium)
2011/01/04 13:46:33
Fix the comment so it's still a sentence (add "and
| |
4892 // mode CONST, and functions. | |
4893 Variable* var = decl->proxy()->var(); | 4921 Variable* var = decl->proxy()->var(); |
4894 Slot* slot = var->AsSlot(); | 4922 Slot* slot = var->AsSlot(); |
4895 if (var->is_global() || | 4923 if (var->is_global() || |
4896 (slot != NULL && slot->type() == Slot::LOOKUP) || | 4924 (slot != NULL && slot->type() == Slot::LOOKUP) || |
4897 decl->mode() == Variable::CONST || | |
4898 decl->fun() != NULL) { | 4925 decl->fun() != NULL) { |
4899 BAILOUT("unsupported declaration"); | 4926 BAILOUT("unsupported declaration"); |
4900 } | 4927 } |
4928 | |
4929 if (var->mode() == Variable::CONST) { | |
Kevin Millikin (Chromium)
2011/01/04 13:46:33
I don't think you should change the test against d
| |
4930 environment()->Bind(var, graph()->GetConstantHole()); | |
Kevin Millikin (Chromium)
2011/01/04 13:46:33
I'm surprised you don't have to check that the var
| |
4931 } | |
4901 } | 4932 } |
4902 | 4933 |
4903 | 4934 |
4904 // Generators for inline runtime functions. | 4935 // Generators for inline runtime functions. |
4905 // Support for types. | 4936 // Support for types. |
4906 void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) { | 4937 void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) { |
4907 ASSERT(argument_count == 1); | 4938 ASSERT(argument_count == 1); |
4908 HValue* value = Pop(); | 4939 HValue* value = Pop(); |
4909 HIsSmi* result = new HIsSmi(value); | 4940 HIsSmi* result = new HIsSmi(value); |
4910 ast_context()->ReturnInstruction(result, ast_id); | 4941 ast_context()->ReturnInstruction(result, ast_id); |
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5674 } | 5705 } |
5675 | 5706 |
5676 #ifdef DEBUG | 5707 #ifdef DEBUG |
5677 if (graph_ != NULL) graph_->Verify(); | 5708 if (graph_ != NULL) graph_->Verify(); |
5678 if (chunk_ != NULL) chunk_->Verify(); | 5709 if (chunk_ != NULL) chunk_->Verify(); |
5679 if (allocator_ != NULL) allocator_->Verify(); | 5710 if (allocator_ != NULL) allocator_->Verify(); |
5680 #endif | 5711 #endif |
5681 } | 5712 } |
5682 | 5713 |
5683 } } // namespace v8::internal | 5714 } } // namespace v8::internal |
OLD | NEW |