| 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 20 matching lines...) Expand all Loading... |
| 31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
| 32 #include "compiler.h" | 32 #include "compiler.h" |
| 33 #include "debug.h" | 33 #include "debug.h" |
| 34 #include "ic-inl.h" | 34 #include "ic-inl.h" |
| 35 #include "jsregexp.h" | 35 #include "jsregexp.h" |
| 36 #include "parser.h" | 36 #include "parser.h" |
| 37 #include "regexp-macro-assembler.h" | 37 #include "regexp-macro-assembler.h" |
| 38 #include "regexp-stack.h" | 38 #include "regexp-stack.h" |
| 39 #include "register-allocator-inl.h" | 39 #include "register-allocator-inl.h" |
| 40 #include "runtime.h" | 40 #include "runtime.h" |
| 41 #include "safe-codegen-ia32.h" |
| 41 #include "scopes.h" | 42 #include "scopes.h" |
| 42 #include "virtual-frame-inl.h" | 43 #include "virtual-frame-inl.h" |
| 43 | 44 |
| 44 namespace v8 { | 45 namespace v8 { |
| 45 namespace internal { | 46 namespace internal { |
| 46 | 47 |
| 47 #define __ ACCESS_MASM(masm_) | 48 #define __ ACCESS_MASM(masm_) |
| 48 | 49 |
| 49 // ------------------------------------------------------------------------- | 50 // ------------------------------------------------------------------------- |
| 50 // Platform-specific DeferredCode functions. | 51 // Platform-specific DeferredCode functions. |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 Result result = | 583 Result result = |
| 583 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 584 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); |
| 584 frame()->Push(&result); | 585 frame()->Push(&result); |
| 585 } else { | 586 } else { |
| 586 // Anything else can be handled normally. | 587 // Anything else can be handled normally. |
| 587 Load(expr); | 588 Load(expr); |
| 588 } | 589 } |
| 589 } | 590 } |
| 590 | 591 |
| 591 | 592 |
| 593 void CodeGenerator::LoadPossiblySafeExpression(Expression* expr) { |
| 594 SafeSyntaxChecker checker; |
| 595 if (checker.Check(expr)) { |
| 596 __ IncrementCounter(&Counters::safe_expression_tried, 1); |
| 597 JumpTarget unsafe; |
| 598 JumpTarget done; |
| 599 Result scratch = allocator_->Allocate(); |
| 600 ASSERT(scratch.is_register()); |
| 601 Result result = allocator_->Allocate(); |
| 602 ASSERT(result.is_register()); |
| 603 SafeGenerator safe_generator(masm_, &unsafe, this, &scratch, &result); |
| 604 result = safe_generator.Generate(expr); |
| 605 frame()->Push(&result); |
| 606 __ IncrementCounter(&Counters::safe_expression_succeeded, 1); |
| 607 done.Jump(); |
| 608 |
| 609 unsafe.Bind(); |
| 610 Load(expr); |
| 611 done.Bind(); |
| 612 } else { |
| 613 Load(expr); |
| 614 } |
| 615 } |
| 616 |
| 617 |
| 592 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { | 618 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { |
| 593 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; | 619 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; |
| 594 ASSERT(scope()->arguments_shadow() != NULL); | 620 ASSERT(scope()->arguments_shadow() != NULL); |
| 595 // We don't want to do lazy arguments allocation for functions that | 621 // We don't want to do lazy arguments allocation for functions that |
| 596 // have heap-allocated contexts, because it interfers with the | 622 // have heap-allocated contexts, because it interfers with the |
| 597 // uninitialized const tracking in the context objects. | 623 // uninitialized const tracking in the context objects. |
| 598 return (scope()->num_heap_slots() > 0) | 624 return (scope()->num_heap_slots() > 0) |
| 599 ? EAGER_ARGUMENTS_ALLOCATION | 625 ? EAGER_ARGUMENTS_ALLOCATION |
| 600 : LAZY_ARGUMENTS_ALLOCATION; | 626 : LAZY_ARGUMENTS_ALLOCATION; |
| 601 } | 627 } |
| (...skipping 2313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2915 CodeForStatementPosition(node); | 2941 CodeForStatementPosition(node); |
| 2916 node->target()->break_target()->Jump(); | 2942 node->target()->break_target()->Jump(); |
| 2917 } | 2943 } |
| 2918 | 2944 |
| 2919 | 2945 |
| 2920 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 2946 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
| 2921 ASSERT(!in_spilled_code()); | 2947 ASSERT(!in_spilled_code()); |
| 2922 Comment cmnt(masm_, "[ ReturnStatement"); | 2948 Comment cmnt(masm_, "[ ReturnStatement"); |
| 2923 | 2949 |
| 2924 CodeForStatementPosition(node); | 2950 CodeForStatementPosition(node); |
| 2925 Load(node->expression()); | 2951 LoadPossiblySafeExpression(node->expression()); |
| 2926 Result return_value = frame_->Pop(); | 2952 Result return_value = frame_->Pop(); |
| 2927 masm()->WriteRecordedPositions(); | 2953 masm()->WriteRecordedPositions(); |
| 2928 if (function_return_is_shadowed_) { | 2954 if (function_return_is_shadowed_) { |
| 2929 function_return_.Jump(&return_value); | 2955 function_return_.Jump(&return_value); |
| 2930 } else { | 2956 } else { |
| 2931 frame_->PrepareForReturn(); | 2957 frame_->PrepareForReturn(); |
| 2932 if (function_return_.is_bound()) { | 2958 if (function_return_.is_bound()) { |
| 2933 // If the function return label is already bound we reuse the | 2959 // If the function return label is already bound we reuse the |
| 2934 // code by jumping to the return site. | 2960 // code by jumping to the return site. |
| 2935 function_return_.Jump(&return_value); | 2961 function_return_.Jump(&return_value); |
| (...skipping 1802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4738 Comment cmnt(masm(), "[ Variable Assignment"); | 4764 Comment cmnt(masm(), "[ Variable Assignment"); |
| 4739 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | 4765 Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
| 4740 ASSERT(var != NULL); | 4766 ASSERT(var != NULL); |
| 4741 Slot* slot = var->slot(); | 4767 Slot* slot = var->slot(); |
| 4742 ASSERT(slot != NULL); | 4768 ASSERT(slot != NULL); |
| 4743 | 4769 |
| 4744 // Evaluate the right-hand side. | 4770 // Evaluate the right-hand side. |
| 4745 if (node->is_compound()) { | 4771 if (node->is_compound()) { |
| 4746 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 4772 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
| 4747 frame()->Push(&result); | 4773 frame()->Push(&result); |
| 4748 Load(node->value()); | 4774 LoadPossiblySafeExpression(node->value()); |
| 4749 | 4775 |
| 4750 bool overwrite_value = | 4776 bool overwrite_value = |
| 4751 (node->value()->AsBinaryOperation() != NULL && | 4777 (node->value()->AsBinaryOperation() != NULL && |
| 4752 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 4778 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
| 4753 GenericBinaryOperation(node->binary_op(), | 4779 GenericBinaryOperation(node->binary_op(), |
| 4754 node->type(), | 4780 node->type(), |
| 4755 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 4781 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
| 4756 } else { | 4782 } else { |
| 4757 Load(node->value()); | 4783 LoadPossiblySafeExpression(node->value()); |
| 4758 } | 4784 } |
| 4759 | 4785 |
| 4760 // Perform the assignment. | 4786 // Perform the assignment. |
| 4761 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { | 4787 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { |
| 4762 CodeForSourcePosition(node->position()); | 4788 CodeForSourcePosition(node->position()); |
| 4763 StoreToSlot(slot, | 4789 StoreToSlot(slot, |
| 4764 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT); | 4790 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT); |
| 4765 } | 4791 } |
| 4766 ASSERT(frame()->height() == original_height + 1); | 4792 ASSERT(frame()->height() == original_height + 1); |
| 4767 } | 4793 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4815 } else if (var != NULL) { | 4841 } else if (var != NULL) { |
| 4816 // The LoadIC stub expects the object in eax. | 4842 // The LoadIC stub expects the object in eax. |
| 4817 // Freeing eax causes the code generator to load the global into it. | 4843 // Freeing eax causes the code generator to load the global into it. |
| 4818 frame_->Spill(eax); | 4844 frame_->Spill(eax); |
| 4819 LoadGlobal(); | 4845 LoadGlobal(); |
| 4820 } else { | 4846 } else { |
| 4821 frame()->Dup(); | 4847 frame()->Dup(); |
| 4822 } | 4848 } |
| 4823 Result value = EmitNamedLoad(name, var != NULL); | 4849 Result value = EmitNamedLoad(name, var != NULL); |
| 4824 frame()->Push(&value); | 4850 frame()->Push(&value); |
| 4825 Load(node->value()); | 4851 LoadPossiblySafeExpression(node->value()); |
| 4826 | 4852 |
| 4827 bool overwrite_value = | 4853 bool overwrite_value = |
| 4828 (node->value()->AsBinaryOperation() != NULL && | 4854 (node->value()->AsBinaryOperation() != NULL && |
| 4829 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 4855 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
| 4830 GenericBinaryOperation(node->binary_op(), | 4856 GenericBinaryOperation(node->binary_op(), |
| 4831 node->type(), | 4857 node->type(), |
| 4832 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 4858 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
| 4833 } else { | 4859 } else { |
| 4834 Load(node->value()); | 4860 LoadPossiblySafeExpression(node->value()); |
| 4835 } | 4861 } |
| 4836 | 4862 |
| 4837 // Perform the assignment. It is safe to ignore constants here. | 4863 // Perform the assignment. It is safe to ignore constants here. |
| 4838 ASSERT(var == NULL || var->mode() != Variable::CONST); | 4864 ASSERT(var == NULL || var->mode() != Variable::CONST); |
| 4839 ASSERT_NE(Token::INIT_CONST, node->op()); | 4865 ASSERT_NE(Token::INIT_CONST, node->op()); |
| 4840 if (is_trivial_receiver) { | 4866 if (is_trivial_receiver) { |
| 4841 Result value = frame()->Pop(); | 4867 Result value = frame()->Pop(); |
| 4842 frame()->Push(prop->obj()); | 4868 frame()->Push(prop->obj()); |
| 4843 frame()->Push(&value); | 4869 frame()->Push(&value); |
| 4844 } | 4870 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4894 // Evaluate the key subexpression. | 4920 // Evaluate the key subexpression. |
| 4895 Load(prop->key()); | 4921 Load(prop->key()); |
| 4896 | 4922 |
| 4897 // Evaluate the right-hand side. | 4923 // Evaluate the right-hand side. |
| 4898 if (node->is_compound()) { | 4924 if (node->is_compound()) { |
| 4899 // Duplicate receiver and key. | 4925 // Duplicate receiver and key. |
| 4900 frame()->PushElementAt(1); | 4926 frame()->PushElementAt(1); |
| 4901 frame()->PushElementAt(1); | 4927 frame()->PushElementAt(1); |
| 4902 Result value = EmitKeyedLoad(); | 4928 Result value = EmitKeyedLoad(); |
| 4903 frame()->Push(&value); | 4929 frame()->Push(&value); |
| 4904 Load(node->value()); | 4930 LoadPossiblySafeExpression(node->value()); |
| 4905 | 4931 |
| 4906 bool overwrite_value = | 4932 bool overwrite_value = |
| 4907 (node->value()->AsBinaryOperation() != NULL && | 4933 (node->value()->AsBinaryOperation() != NULL && |
| 4908 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 4934 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
| 4909 GenericBinaryOperation(node->binary_op(), | 4935 GenericBinaryOperation(node->binary_op(), |
| 4910 node->type(), | 4936 node->type(), |
| 4911 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 4937 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
| 4912 } else { | 4938 } else { |
| 4913 Load(node->value()); | 4939 LoadPossiblySafeExpression(node->value()); |
| 4914 } | 4940 } |
| 4915 | 4941 |
| 4916 // Perform the assignment. It is safe to ignore constants here. | 4942 // Perform the assignment. It is safe to ignore constants here. |
| 4917 ASSERT(node->op() != Token::INIT_CONST); | 4943 ASSERT(node->op() != Token::INIT_CONST); |
| 4918 CodeForSourcePosition(node->position()); | 4944 CodeForSourcePosition(node->position()); |
| 4919 Result answer = EmitKeyedStore(prop->key()->type()); | 4945 Result answer = EmitKeyedStore(prop->key()->type()); |
| 4920 frame()->Push(&answer); | 4946 frame()->Push(&answer); |
| 4921 | 4947 |
| 4922 if (node->ends_initialization_block()) { | 4948 if (node->ends_initialization_block()) { |
| 4923 // The argument to the runtime call is the extra copy of the receiver, | 4949 // The argument to the runtime call is the extra copy of the receiver, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5013 // call. Then we call the resolved function using the given | 5039 // call. Then we call the resolved function using the given |
| 5014 // arguments. | 5040 // arguments. |
| 5015 | 5041 |
| 5016 // Prepare the stack for the call to the resolved function. | 5042 // Prepare the stack for the call to the resolved function. |
| 5017 Load(function); | 5043 Load(function); |
| 5018 | 5044 |
| 5019 // Allocate a frame slot for the receiver. | 5045 // Allocate a frame slot for the receiver. |
| 5020 frame_->Push(Factory::undefined_value()); | 5046 frame_->Push(Factory::undefined_value()); |
| 5021 int arg_count = args->length(); | 5047 int arg_count = args->length(); |
| 5022 for (int i = 0; i < arg_count; i++) { | 5048 for (int i = 0; i < arg_count; i++) { |
| 5023 Load(args->at(i)); | 5049 LoadPossiblySafeExpression(args->at(i)); |
| 5024 } | 5050 } |
| 5025 | 5051 |
| 5026 // Prepare the stack for the call to ResolvePossiblyDirectEval. | 5052 // Prepare the stack for the call to ResolvePossiblyDirectEval. |
| 5027 frame_->PushElementAt(arg_count + 1); | 5053 frame_->PushElementAt(arg_count + 1); |
| 5028 if (arg_count > 0) { | 5054 if (arg_count > 0) { |
| 5029 frame_->PushElementAt(arg_count); | 5055 frame_->PushElementAt(arg_count); |
| 5030 } else { | 5056 } else { |
| 5031 frame_->Push(Factory::undefined_value()); | 5057 frame_->Push(Factory::undefined_value()); |
| 5032 } | 5058 } |
| 5033 | 5059 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 5062 // ---------------------------------- | 5088 // ---------------------------------- |
| 5063 | 5089 |
| 5064 // Pass the global object as the receiver and let the IC stub | 5090 // Pass the global object as the receiver and let the IC stub |
| 5065 // patch the stack to use the global proxy as 'this' in the | 5091 // patch the stack to use the global proxy as 'this' in the |
| 5066 // invoked function. | 5092 // invoked function. |
| 5067 LoadGlobal(); | 5093 LoadGlobal(); |
| 5068 | 5094 |
| 5069 // Load the arguments. | 5095 // Load the arguments. |
| 5070 int arg_count = args->length(); | 5096 int arg_count = args->length(); |
| 5071 for (int i = 0; i < arg_count; i++) { | 5097 for (int i = 0; i < arg_count; i++) { |
| 5072 Load(args->at(i)); | 5098 LoadPossiblySafeExpression(args->at(i)); |
| 5073 } | 5099 } |
| 5074 | 5100 |
| 5075 // Push the name of the function onto the frame. | 5101 // Push the name of the function onto the frame. |
| 5076 frame_->Push(var->name()); | 5102 frame_->Push(var->name()); |
| 5077 | 5103 |
| 5078 // Call the IC initialization code. | 5104 // Call the IC initialization code. |
| 5079 CodeForSourcePosition(node->position()); | 5105 CodeForSourcePosition(node->position()); |
| 5080 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, | 5106 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, |
| 5081 arg_count, | 5107 arg_count, |
| 5082 loop_nesting()); | 5108 loop_nesting()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5133 args->at(1)->AsVariableProxy(), | 5159 args->at(1)->AsVariableProxy(), |
| 5134 node->position()); | 5160 node->position()); |
| 5135 | 5161 |
| 5136 } else { | 5162 } else { |
| 5137 // Push the receiver onto the frame. | 5163 // Push the receiver onto the frame. |
| 5138 Load(property->obj()); | 5164 Load(property->obj()); |
| 5139 | 5165 |
| 5140 // Load the arguments. | 5166 // Load the arguments. |
| 5141 int arg_count = args->length(); | 5167 int arg_count = args->length(); |
| 5142 for (int i = 0; i < arg_count; i++) { | 5168 for (int i = 0; i < arg_count; i++) { |
| 5143 Load(args->at(i)); | 5169 LoadPossiblySafeExpression(args->at(i)); |
| 5144 } | 5170 } |
| 5145 | 5171 |
| 5146 // Push the name of the function onto the frame. | 5172 // Push the name of the function onto the frame. |
| 5147 frame_->Push(name); | 5173 frame_->Push(name); |
| 5148 | 5174 |
| 5149 // Call the IC initialization code. | 5175 // Call the IC initialization code. |
| 5150 CodeForSourcePosition(node->position()); | 5176 CodeForSourcePosition(node->position()); |
| 5151 Result result = | 5177 Result result = |
| 5152 frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, | 5178 frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, |
| 5153 loop_nesting()); | 5179 loop_nesting()); |
| (...skipping 6126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11280 | 11306 |
| 11281 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 11307 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 11282 // tagged as a small integer. | 11308 // tagged as a small integer. |
| 11283 __ bind(&runtime); | 11309 __ bind(&runtime); |
| 11284 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 11310 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 11285 } | 11311 } |
| 11286 | 11312 |
| 11287 #undef __ | 11313 #undef __ |
| 11288 | 11314 |
| 11289 } } // namespace v8::internal | 11315 } } // namespace v8::internal |
| OLD | NEW |