Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: src/full-codegen/full-codegen.cc

Issue 1969423002: [Interpreter] Remove InterpreterExitTrampoline and replace with returning to the entry trampoline. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix typo on Arm64 Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/full-codegen/full-codegen.h" 5 #include "src/full-codegen/full-codegen.h"
6 6
7 #include "src/ast/ast-numbering.h" 7 #include "src/ast/ast-numbering.h"
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/prettyprinter.h" 9 #include "src/ast/prettyprinter.h"
10 #include "src/ast/scopeinfo.h" 10 #include "src/ast/scopeinfo.h"
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 expr->values()->length() > JSArray::kInitialMaxFastElementArray; 155 expr->values()->length() > JSArray::kInitialMaxFastElementArray;
156 } 156 }
157 157
158 158
159 void FullCodeGenerator::Initialize() { 159 void FullCodeGenerator::Initialize() {
160 InitializeAstVisitor(info_->isolate()); 160 InitializeAstVisitor(info_->isolate());
161 masm_->set_emit_debug_code(FLAG_debug_code); 161 masm_->set_emit_debug_code(FLAG_debug_code);
162 masm_->set_predictable_code_size(true); 162 masm_->set_predictable_code_size(true);
163 } 163 }
164 164
165 165 void FullCodeGenerator::PrepareForBailout(Expression* node,
166 void FullCodeGenerator::PrepareForBailout(Expression* node, State state) { 166 Deoptimizer::BailoutState state) {
167 PrepareForBailoutForId(node->id(), state); 167 PrepareForBailoutForId(node->id(), state);
168 } 168 }
169 169
170 170
171 void FullCodeGenerator::CallLoadIC(TypeofMode typeof_mode, 171 void FullCodeGenerator::CallLoadIC(TypeofMode typeof_mode,
172 TypeFeedbackId id) { 172 TypeFeedbackId id) {
173 Handle<Code> ic = CodeFactory::LoadIC(isolate(), typeof_mode).code(); 173 Handle<Code> ic = CodeFactory::LoadIC(isolate(), typeof_mode).code();
174 CallIC(ic, id); 174 CallIC(ic, id);
175 } 175 }
176 176
177 177
178 void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) { 178 void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
179 Handle<Code> ic = CodeFactory::StoreIC(isolate(), language_mode()).code(); 179 Handle<Code> ic = CodeFactory::StoreIC(isolate(), language_mode()).code();
180 CallIC(ic, id); 180 CallIC(ic, id);
181 } 181 }
182 182
183 183
184 void FullCodeGenerator::RecordJSReturnSite(Call* call) { 184 void FullCodeGenerator::RecordJSReturnSite(Call* call) {
185 // We record the offset of the function return so we can rebuild the frame 185 // We record the offset of the function return so we can rebuild the frame
186 // if the function was inlined, i.e., this is the return address in the 186 // if the function was inlined, i.e., this is the return address in the
187 // inlined function's frame. 187 // inlined function's frame.
188 // 188 //
189 // The state is ignored. We defensively set it to TOS_REG, which is the 189 // The bailout state is ignored. We defensively set it to TOS_REGISTER, which
190 // real state of the unoptimized code at the return site. 190 // is the real state of the unoptimized code at the return site.
191 PrepareForBailoutForId(call->ReturnId(), TOS_REG); 191 PrepareForBailoutForId(call->ReturnId(),
192 Deoptimizer::BailoutState::TOS_REGISTER);
192 #ifdef DEBUG 193 #ifdef DEBUG
193 // In debug builds, mark the return so we can verify that this function 194 // In debug builds, mark the return so we can verify that this function
194 // was called. 195 // was called.
195 DCHECK(!call->return_is_recorded_); 196 DCHECK(!call->return_is_recorded_);
196 call->return_is_recorded_ = true; 197 call->return_is_recorded_ = true;
197 #endif 198 #endif
198 } 199 }
199 200
200 201 void FullCodeGenerator::PrepareForBailoutForId(
201 void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) { 202 BailoutId id, Deoptimizer::BailoutState state) {
202 // There's no need to prepare this code for bailouts from already optimized 203 // There's no need to prepare this code for bailouts from already optimized
203 // code or code that can't be optimized. 204 // code or code that can't be optimized.
204 if (!info_->HasDeoptimizationSupport()) return; 205 if (!info_->HasDeoptimizationSupport()) return;
205 unsigned pc_and_state = 206 unsigned pc_and_state =
206 StateField::encode(state) | PcField::encode(masm_->pc_offset()); 207 BailoutStateField::encode(state) | PcField::encode(masm_->pc_offset());
207 DCHECK(Smi::IsValid(pc_and_state)); 208 DCHECK(Smi::IsValid(pc_and_state));
208 #ifdef DEBUG 209 #ifdef DEBUG
209 for (int i = 0; i < bailout_entries_.length(); ++i) { 210 for (int i = 0; i < bailout_entries_.length(); ++i) {
210 DCHECK(bailout_entries_[i].id != id); 211 DCHECK(bailout_entries_[i].id != id);
211 } 212 }
212 #endif 213 #endif
213 BailoutEntry entry = { id, pc_and_state }; 214 BailoutEntry entry = { id, pc_and_state };
214 bailout_entries_.Add(entry, zone()); 215 bailout_entries_.Add(entry, zone());
215 } 216 }
216 217
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 Label done; 744 Label done;
744 745
745 if (context()->IsTest()) { 746 if (context()->IsTest()) {
746 Label eval_right; 747 Label eval_right;
747 const TestContext* test = TestContext::cast(context()); 748 const TestContext* test = TestContext::cast(context());
748 if (is_logical_and) { 749 if (is_logical_and) {
749 VisitForControl(left, &eval_right, test->false_label(), &eval_right); 750 VisitForControl(left, &eval_right, test->false_label(), &eval_right);
750 } else { 751 } else {
751 VisitForControl(left, test->true_label(), &eval_right, &eval_right); 752 VisitForControl(left, test->true_label(), &eval_right, &eval_right);
752 } 753 }
753 PrepareForBailoutForId(right_id, NO_REGISTERS); 754 PrepareForBailoutForId(right_id, Deoptimizer::BailoutState::NO_REGISTERS);
754 __ bind(&eval_right); 755 __ bind(&eval_right);
755 756
756 } else if (context()->IsAccumulatorValue()) { 757 } else if (context()->IsAccumulatorValue()) {
757 VisitForAccumulatorValue(left); 758 VisitForAccumulatorValue(left);
758 // We want the value in the accumulator for the test, and on the stack in 759 // We want the value in the accumulator for the test, and on the stack in
759 // case we need it. 760 // case we need it.
760 __ Push(result_register()); 761 __ Push(result_register());
761 Label discard, restore; 762 Label discard, restore;
762 if (is_logical_and) { 763 if (is_logical_and) {
763 DoTest(left, &discard, &restore, &restore); 764 DoTest(left, &discard, &restore, &restore);
764 } else { 765 } else {
765 DoTest(left, &restore, &discard, &restore); 766 DoTest(left, &restore, &discard, &restore);
766 } 767 }
767 __ bind(&restore); 768 __ bind(&restore);
768 __ Pop(result_register()); 769 __ Pop(result_register());
769 __ jmp(&done); 770 __ jmp(&done);
770 __ bind(&discard); 771 __ bind(&discard);
771 __ Drop(1); 772 __ Drop(1);
772 PrepareForBailoutForId(right_id, NO_REGISTERS); 773 PrepareForBailoutForId(right_id, Deoptimizer::BailoutState::NO_REGISTERS);
773 774
774 } else if (context()->IsStackValue()) { 775 } else if (context()->IsStackValue()) {
775 VisitForAccumulatorValue(left); 776 VisitForAccumulatorValue(left);
776 // We want the value in the accumulator for the test, and on the stack in 777 // We want the value in the accumulator for the test, and on the stack in
777 // case we need it. 778 // case we need it.
778 __ Push(result_register()); 779 __ Push(result_register());
779 Label discard; 780 Label discard;
780 if (is_logical_and) { 781 if (is_logical_and) {
781 DoTest(left, &discard, &done, &discard); 782 DoTest(left, &discard, &done, &discard);
782 } else { 783 } else {
783 DoTest(left, &done, &discard, &discard); 784 DoTest(left, &done, &discard, &discard);
784 } 785 }
785 __ bind(&discard); 786 __ bind(&discard);
786 __ Drop(1); 787 __ Drop(1);
787 PrepareForBailoutForId(right_id, NO_REGISTERS); 788 PrepareForBailoutForId(right_id, Deoptimizer::BailoutState::NO_REGISTERS);
788 789
789 } else { 790 } else {
790 DCHECK(context()->IsEffect()); 791 DCHECK(context()->IsEffect());
791 Label eval_right; 792 Label eval_right;
792 if (is_logical_and) { 793 if (is_logical_and) {
793 VisitForControl(left, &eval_right, &done, &eval_right); 794 VisitForControl(left, &eval_right, &done, &eval_right);
794 } else { 795 } else {
795 VisitForControl(left, &done, &eval_right, &eval_right); 796 VisitForControl(left, &done, &eval_right, &eval_right);
796 } 797 }
797 PrepareForBailoutForId(right_id, NO_REGISTERS); 798 PrepareForBailoutForId(right_id, Deoptimizer::BailoutState::NO_REGISTERS);
798 __ bind(&eval_right); 799 __ bind(&eval_right);
799 } 800 }
800 801
801 VisitInDuplicateContext(right); 802 VisitInDuplicateContext(right);
802 __ bind(&done); 803 __ bind(&done);
803 } 804 }
804 805
805 806
806 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { 807 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
807 Token::Value op = expr->op(); 808 Token::Value op = expr->op();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 PopOperand(LoadDescriptor::ReceiverRegister()); 846 PopOperand(LoadDescriptor::ReceiverRegister());
846 EmitKeyedPropertyLoad(expr); 847 EmitKeyedPropertyLoad(expr);
847 } else { 848 } else {
848 VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var()); 849 VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
849 VisitForStackValue( 850 VisitForStackValue(
850 expr->obj()->AsSuperPropertyReference()->home_object()); 851 expr->obj()->AsSuperPropertyReference()->home_object());
851 VisitForStackValue(expr->key()); 852 VisitForStackValue(expr->key());
852 EmitKeyedSuperPropertyLoad(expr); 853 EmitKeyedSuperPropertyLoad(expr);
853 } 854 }
854 } 855 }
855 PrepareForBailoutForId(expr->LoadId(), TOS_REG); 856 PrepareForBailoutForId(expr->LoadId(),
857 Deoptimizer::BailoutState::TOS_REGISTER);
856 context()->Plug(result_register()); 858 context()->Plug(result_register());
857 } 859 }
858 860
859 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 861 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
860 VariableProxy* proxy = expr->AsVariableProxy(); 862 VariableProxy* proxy = expr->AsVariableProxy();
861 DCHECK(!context()->IsEffect()); 863 DCHECK(!context()->IsEffect());
862 DCHECK(!context()->IsTest()); 864 DCHECK(!context()->IsTest());
863 865
864 if (proxy != NULL && (proxy->var()->IsUnallocatedOrGlobalSlot() || 866 if (proxy != NULL && (proxy->var()->IsUnallocatedOrGlobalSlot() ||
865 proxy->var()->IsLookupSlot())) { 867 proxy->var()->IsLookupSlot())) {
866 EmitVariableLoad(proxy, INSIDE_TYPEOF); 868 EmitVariableLoad(proxy, INSIDE_TYPEOF);
867 PrepareForBailout(proxy, TOS_REG); 869 PrepareForBailout(proxy, Deoptimizer::BailoutState::TOS_REGISTER);
868 } else { 870 } else {
869 // This expression cannot throw a reference error at the top level. 871 // This expression cannot throw a reference error at the top level.
870 VisitInDuplicateContext(expr); 872 VisitInDuplicateContext(expr);
871 } 873 }
872 } 874 }
873 875
874 876
875 void FullCodeGenerator::VisitBlock(Block* stmt) { 877 void FullCodeGenerator::VisitBlock(Block* stmt) {
876 Comment cmnt(masm_, "[ Block"); 878 Comment cmnt(masm_, "[ Block");
877 NestedBlock nested_block(this, stmt); 879 NestedBlock nested_block(this, stmt);
(...skipping 27 matching lines...) Expand all
905 } 907 }
906 908
907 909
908 void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) { 910 void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
909 Comment cmnt(masm_, "[ IfStatement"); 911 Comment cmnt(masm_, "[ IfStatement");
910 SetStatementPosition(stmt); 912 SetStatementPosition(stmt);
911 Label then_part, else_part, done; 913 Label then_part, else_part, done;
912 914
913 if (stmt->HasElseStatement()) { 915 if (stmt->HasElseStatement()) {
914 VisitForControl(stmt->condition(), &then_part, &else_part, &then_part); 916 VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
915 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS); 917 PrepareForBailoutForId(stmt->ThenId(),
918 Deoptimizer::BailoutState::NO_REGISTERS);
916 __ bind(&then_part); 919 __ bind(&then_part);
917 Visit(stmt->then_statement()); 920 Visit(stmt->then_statement());
918 __ jmp(&done); 921 __ jmp(&done);
919 922
920 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); 923 PrepareForBailoutForId(stmt->ElseId(),
924 Deoptimizer::BailoutState::NO_REGISTERS);
921 __ bind(&else_part); 925 __ bind(&else_part);
922 Visit(stmt->else_statement()); 926 Visit(stmt->else_statement());
923 } else { 927 } else {
924 VisitForControl(stmt->condition(), &then_part, &done, &then_part); 928 VisitForControl(stmt->condition(), &then_part, &done, &then_part);
925 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS); 929 PrepareForBailoutForId(stmt->ThenId(),
930 Deoptimizer::BailoutState::NO_REGISTERS);
926 __ bind(&then_part); 931 __ bind(&then_part);
927 Visit(stmt->then_statement()); 932 Visit(stmt->then_statement());
928 933
929 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); 934 PrepareForBailoutForId(stmt->ElseId(),
935 Deoptimizer::BailoutState::NO_REGISTERS);
930 } 936 }
931 __ bind(&done); 937 __ bind(&done);
932 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); 938 PrepareForBailoutForId(stmt->IfId(), Deoptimizer::BailoutState::NO_REGISTERS);
933 } 939 }
934 940
935 void FullCodeGenerator::EmitContinue(Statement* target) { 941 void FullCodeGenerator::EmitContinue(Statement* target) {
936 NestedStatement* current = nesting_stack_; 942 NestedStatement* current = nesting_stack_;
937 int context_length = 0; 943 int context_length = 0;
938 // When continuing, we clobber the unpredictable value in the accumulator 944 // When continuing, we clobber the unpredictable value in the accumulator
939 // with one that's safe for GC. If we hit an exit from the try block of 945 // with one that's safe for GC. If we hit an exit from the try block of
940 // try...finally on our way out, we will unconditionally preserve the 946 // try...finally on our way out, we will unconditionally preserve the
941 // accumulator on the stack. 947 // accumulator on the stack.
942 ClearAccumulator(); 948 ClearAccumulator();
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { 1092 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
1087 // Stack: receiver, home_object, key. 1093 // Stack: receiver, home_object, key.
1088 SetExpressionPosition(prop); 1094 SetExpressionPosition(prop);
1089 CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper); 1095 CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
1090 } 1096 }
1091 1097
1092 void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property, 1098 void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property,
1093 BailoutId bailout_id) { 1099 BailoutId bailout_id) {
1094 VisitForStackValue(property->key()); 1100 VisitForStackValue(property->key());
1095 CallRuntimeWithOperands(Runtime::kToName); 1101 CallRuntimeWithOperands(Runtime::kToName);
1096 PrepareForBailoutForId(bailout_id, NO_REGISTERS); 1102 PrepareForBailoutForId(bailout_id, Deoptimizer::BailoutState::NO_REGISTERS);
1097 PushOperand(result_register()); 1103 PushOperand(result_register());
1098 } 1104 }
1099 1105
1100 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { 1106 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) {
1101 DCHECK(!slot.IsInvalid()); 1107 DCHECK(!slot.IsInvalid());
1102 __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot)); 1108 __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot));
1103 } 1109 }
1104 1110
1105 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 1111 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
1106 Comment cmnt(masm_, "[ ReturnStatement"); 1112 Comment cmnt(masm_, "[ ReturnStatement");
1107 SetStatementPosition(stmt); 1113 SetStatementPosition(stmt);
1108 Expression* expr = stmt->expression(); 1114 Expression* expr = stmt->expression();
1109 VisitForAccumulatorValue(expr); 1115 VisitForAccumulatorValue(expr);
1110 EmitUnwindAndReturn(); 1116 EmitUnwindAndReturn();
1111 } 1117 }
1112 1118
1113 1119
1114 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { 1120 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
1115 Comment cmnt(masm_, "[ WithStatement"); 1121 Comment cmnt(masm_, "[ WithStatement");
1116 SetStatementPosition(stmt); 1122 SetStatementPosition(stmt);
1117 1123
1118 VisitForAccumulatorValue(stmt->expression()); 1124 VisitForAccumulatorValue(stmt->expression());
1119 Callable callable = CodeFactory::ToObject(isolate()); 1125 Callable callable = CodeFactory::ToObject(isolate());
1120 __ Move(callable.descriptor().GetRegisterParameter(0), result_register()); 1126 __ Move(callable.descriptor().GetRegisterParameter(0), result_register());
1121 __ Call(callable.code(), RelocInfo::CODE_TARGET); 1127 __ Call(callable.code(), RelocInfo::CODE_TARGET);
1122 PrepareForBailoutForId(stmt->ToObjectId(), NO_REGISTERS); 1128 PrepareForBailoutForId(stmt->ToObjectId(),
1129 Deoptimizer::BailoutState::NO_REGISTERS);
1123 PushOperand(result_register()); 1130 PushOperand(result_register());
1124 PushFunctionArgumentForContextAllocation(); 1131 PushFunctionArgumentForContextAllocation();
1125 CallRuntimeWithOperands(Runtime::kPushWithContext); 1132 CallRuntimeWithOperands(Runtime::kPushWithContext);
1126 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); 1133 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1127 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 1134 PrepareForBailoutForId(stmt->EntryId(),
1135 Deoptimizer::BailoutState::NO_REGISTERS);
1128 1136
1129 Scope* saved_scope = scope(); 1137 Scope* saved_scope = scope();
1130 scope_ = stmt->scope(); 1138 scope_ = stmt->scope();
1131 { WithOrCatch body(this); 1139 { WithOrCatch body(this);
1132 Visit(stmt->statement()); 1140 Visit(stmt->statement());
1133 } 1141 }
1134 scope_ = saved_scope; 1142 scope_ = saved_scope;
1135 1143
1136 // Pop context. 1144 // Pop context.
1137 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 1145 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
(...skipping 11 matching lines...) Expand all
1149 1157
1150 Iteration loop_statement(this, stmt); 1158 Iteration loop_statement(this, stmt);
1151 increment_loop_depth(); 1159 increment_loop_depth();
1152 1160
1153 __ bind(&body); 1161 __ bind(&body);
1154 Visit(stmt->body()); 1162 Visit(stmt->body());
1155 1163
1156 // Record the position of the do while condition and make sure it is 1164 // Record the position of the do while condition and make sure it is
1157 // possible to break on the condition. 1165 // possible to break on the condition.
1158 __ bind(loop_statement.continue_label()); 1166 __ bind(loop_statement.continue_label());
1159 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); 1167 PrepareForBailoutForId(stmt->ContinueId(),
1168 Deoptimizer::BailoutState::NO_REGISTERS);
1160 1169
1161 // Here is the actual 'while' keyword. 1170 // Here is the actual 'while' keyword.
1162 SetExpressionAsStatementPosition(stmt->cond()); 1171 SetExpressionAsStatementPosition(stmt->cond());
1163 VisitForControl(stmt->cond(), 1172 VisitForControl(stmt->cond(),
1164 &book_keeping, 1173 &book_keeping,
1165 loop_statement.break_label(), 1174 loop_statement.break_label(),
1166 &book_keeping); 1175 &book_keeping);
1167 1176
1168 // Check stack before looping. 1177 // Check stack before looping.
1169 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); 1178 PrepareForBailoutForId(stmt->BackEdgeId(),
1179 Deoptimizer::BailoutState::NO_REGISTERS);
1170 __ bind(&book_keeping); 1180 __ bind(&book_keeping);
1171 EmitBackEdgeBookkeeping(stmt, &body); 1181 EmitBackEdgeBookkeeping(stmt, &body);
1172 __ jmp(&body); 1182 __ jmp(&body);
1173 1183
1174 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1184 PrepareForBailoutForId(stmt->ExitId(),
1185 Deoptimizer::BailoutState::NO_REGISTERS);
1175 __ bind(loop_statement.break_label()); 1186 __ bind(loop_statement.break_label());
1176 decrement_loop_depth(); 1187 decrement_loop_depth();
1177 } 1188 }
1178 1189
1179 1190
1180 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 1191 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1181 Comment cmnt(masm_, "[ WhileStatement"); 1192 Comment cmnt(masm_, "[ WhileStatement");
1182 Label loop, body; 1193 Label loop, body;
1183 1194
1184 Iteration loop_statement(this, stmt); 1195 Iteration loop_statement(this, stmt);
1185 increment_loop_depth(); 1196 increment_loop_depth();
1186 1197
1187 __ bind(&loop); 1198 __ bind(&loop);
1188 1199
1189 SetExpressionAsStatementPosition(stmt->cond()); 1200 SetExpressionAsStatementPosition(stmt->cond());
1190 VisitForControl(stmt->cond(), 1201 VisitForControl(stmt->cond(),
1191 &body, 1202 &body,
1192 loop_statement.break_label(), 1203 loop_statement.break_label(),
1193 &body); 1204 &body);
1194 1205
1195 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1206 PrepareForBailoutForId(stmt->BodyId(),
1207 Deoptimizer::BailoutState::NO_REGISTERS);
1196 __ bind(&body); 1208 __ bind(&body);
1197 Visit(stmt->body()); 1209 Visit(stmt->body());
1198 1210
1199 __ bind(loop_statement.continue_label()); 1211 __ bind(loop_statement.continue_label());
1200 1212
1201 // Check stack before looping. 1213 // Check stack before looping.
1202 EmitBackEdgeBookkeeping(stmt, &loop); 1214 EmitBackEdgeBookkeeping(stmt, &loop);
1203 __ jmp(&loop); 1215 __ jmp(&loop);
1204 1216
1205 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1217 PrepareForBailoutForId(stmt->ExitId(),
1218 Deoptimizer::BailoutState::NO_REGISTERS);
1206 __ bind(loop_statement.break_label()); 1219 __ bind(loop_statement.break_label());
1207 decrement_loop_depth(); 1220 decrement_loop_depth();
1208 } 1221 }
1209 1222
1210 1223
1211 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { 1224 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1212 Comment cmnt(masm_, "[ ForStatement"); 1225 Comment cmnt(masm_, "[ ForStatement");
1213 // Do not insert break location as we do it below. 1226 // Do not insert break location as we do it below.
1214 SetStatementPosition(stmt, SKIP_BREAK); 1227 SetStatementPosition(stmt, SKIP_BREAK);
1215 1228
1216 Label test, body; 1229 Label test, body;
1217 1230
1218 Iteration loop_statement(this, stmt); 1231 Iteration loop_statement(this, stmt);
1219 1232
1220 if (stmt->init() != NULL) { 1233 if (stmt->init() != NULL) {
1221 Visit(stmt->init()); 1234 Visit(stmt->init());
1222 } 1235 }
1223 1236
1224 increment_loop_depth(); 1237 increment_loop_depth();
1225 // Emit the test at the bottom of the loop (even if empty). 1238 // Emit the test at the bottom of the loop (even if empty).
1226 __ jmp(&test); 1239 __ jmp(&test);
1227 1240
1228 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1241 PrepareForBailoutForId(stmt->BodyId(),
1242 Deoptimizer::BailoutState::NO_REGISTERS);
1229 __ bind(&body); 1243 __ bind(&body);
1230 Visit(stmt->body()); 1244 Visit(stmt->body());
1231 1245
1232 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); 1246 PrepareForBailoutForId(stmt->ContinueId(),
1247 Deoptimizer::BailoutState::NO_REGISTERS);
1233 __ bind(loop_statement.continue_label()); 1248 __ bind(loop_statement.continue_label());
1234 if (stmt->next() != NULL) { 1249 if (stmt->next() != NULL) {
1235 SetStatementPosition(stmt->next()); 1250 SetStatementPosition(stmt->next());
1236 Visit(stmt->next()); 1251 Visit(stmt->next());
1237 } 1252 }
1238 1253
1239 // Check stack before looping. 1254 // Check stack before looping.
1240 EmitBackEdgeBookkeeping(stmt, &body); 1255 EmitBackEdgeBookkeeping(stmt, &body);
1241 1256
1242 __ bind(&test); 1257 __ bind(&test);
1243 if (stmt->cond() != NULL) { 1258 if (stmt->cond() != NULL) {
1244 SetExpressionAsStatementPosition(stmt->cond()); 1259 SetExpressionAsStatementPosition(stmt->cond());
1245 VisitForControl(stmt->cond(), 1260 VisitForControl(stmt->cond(),
1246 &body, 1261 &body,
1247 loop_statement.break_label(), 1262 loop_statement.break_label(),
1248 loop_statement.break_label()); 1263 loop_statement.break_label());
1249 } else { 1264 } else {
1250 __ jmp(&body); 1265 __ jmp(&body);
1251 } 1266 }
1252 1267
1253 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1268 PrepareForBailoutForId(stmt->ExitId(),
1269 Deoptimizer::BailoutState::NO_REGISTERS);
1254 __ bind(loop_statement.break_label()); 1270 __ bind(loop_statement.break_label());
1255 decrement_loop_depth(); 1271 decrement_loop_depth();
1256 } 1272 }
1257 1273
1258 1274
1259 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 1275 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1260 Comment cmnt(masm_, "[ ForOfStatement"); 1276 Comment cmnt(masm_, "[ ForOfStatement");
1261 1277
1262 Iteration loop_statement(this, stmt); 1278 Iteration loop_statement(this, stmt);
1263 increment_loop_depth(); 1279 increment_loop_depth();
(...skipping 15 matching lines...) Expand all
1279 &result_not_done, &result_not_done); 1295 &result_not_done, &result_not_done);
1280 __ bind(&result_not_done); 1296 __ bind(&result_not_done);
1281 1297
1282 // each = result.value 1298 // each = result.value
1283 VisitForEffect(stmt->assign_each()); 1299 VisitForEffect(stmt->assign_each());
1284 1300
1285 // Generate code for the body of the loop. 1301 // Generate code for the body of the loop.
1286 Visit(stmt->body()); 1302 Visit(stmt->body());
1287 1303
1288 // Check stack before looping. 1304 // Check stack before looping.
1289 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); 1305 PrepareForBailoutForId(stmt->BackEdgeId(),
1306 Deoptimizer::BailoutState::NO_REGISTERS);
1290 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); 1307 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
1291 __ jmp(loop_statement.continue_label()); 1308 __ jmp(loop_statement.continue_label());
1292 1309
1293 // Exit and decrement the loop depth. 1310 // Exit and decrement the loop depth.
1294 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1311 PrepareForBailoutForId(stmt->ExitId(),
1312 Deoptimizer::BailoutState::NO_REGISTERS);
1295 __ bind(loop_statement.break_label()); 1313 __ bind(loop_statement.break_label());
1296 decrement_loop_depth(); 1314 decrement_loop_depth();
1297 } 1315 }
1298 1316
1299 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 1317 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1300 LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset, 1318 LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset,
1301 result_register()); 1319 result_register());
1302 context()->Plug(result_register()); 1320 context()->Plug(result_register());
1303 } 1321 }
1304 1322
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 } 1446 }
1429 1447
1430 1448
1431 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { 1449 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1432 Comment cmnt(masm_, "[ DebuggerStatement"); 1450 Comment cmnt(masm_, "[ DebuggerStatement");
1433 SetStatementPosition(stmt); 1451 SetStatementPosition(stmt);
1434 1452
1435 __ DebugBreak(); 1453 __ DebugBreak();
1436 // Ignore the return value. 1454 // Ignore the return value.
1437 1455
1438 PrepareForBailoutForId(stmt->DebugBreakId(), NO_REGISTERS); 1456 PrepareForBailoutForId(stmt->DebugBreakId(),
1457 Deoptimizer::BailoutState::NO_REGISTERS);
1439 } 1458 }
1440 1459
1441 1460
1442 void FullCodeGenerator::VisitCaseClause(CaseClause* clause) { 1461 void FullCodeGenerator::VisitCaseClause(CaseClause* clause) {
1443 UNREACHABLE(); 1462 UNREACHABLE();
1444 } 1463 }
1445 1464
1446 1465
1447 void FullCodeGenerator::VisitConditional(Conditional* expr) { 1466 void FullCodeGenerator::VisitConditional(Conditional* expr) {
1448 Comment cmnt(masm_, "[ Conditional"); 1467 Comment cmnt(masm_, "[ Conditional");
1449 Label true_case, false_case, done; 1468 Label true_case, false_case, done;
1450 VisitForControl(expr->condition(), &true_case, &false_case, &true_case); 1469 VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
1451 1470
1452 int original_stack_depth = operand_stack_depth_; 1471 int original_stack_depth = operand_stack_depth_;
1453 PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS); 1472 PrepareForBailoutForId(expr->ThenId(),
1473 Deoptimizer::BailoutState::NO_REGISTERS);
1454 __ bind(&true_case); 1474 __ bind(&true_case);
1455 SetExpressionPosition(expr->then_expression()); 1475 SetExpressionPosition(expr->then_expression());
1456 if (context()->IsTest()) { 1476 if (context()->IsTest()) {
1457 const TestContext* for_test = TestContext::cast(context()); 1477 const TestContext* for_test = TestContext::cast(context());
1458 VisitForControl(expr->then_expression(), 1478 VisitForControl(expr->then_expression(),
1459 for_test->true_label(), 1479 for_test->true_label(),
1460 for_test->false_label(), 1480 for_test->false_label(),
1461 NULL); 1481 NULL);
1462 } else { 1482 } else {
1463 VisitInDuplicateContext(expr->then_expression()); 1483 VisitInDuplicateContext(expr->then_expression());
1464 __ jmp(&done); 1484 __ jmp(&done);
1465 } 1485 }
1466 1486
1467 operand_stack_depth_ = original_stack_depth; 1487 operand_stack_depth_ = original_stack_depth;
1468 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); 1488 PrepareForBailoutForId(expr->ElseId(),
1489 Deoptimizer::BailoutState::NO_REGISTERS);
1469 __ bind(&false_case); 1490 __ bind(&false_case);
1470 SetExpressionPosition(expr->else_expression()); 1491 SetExpressionPosition(expr->else_expression());
1471 VisitInDuplicateContext(expr->else_expression()); 1492 VisitInDuplicateContext(expr->else_expression());
1472 // If control flow falls through Visit, merge it with true case here. 1493 // If control flow falls through Visit, merge it with true case here.
1473 if (!context()->IsTest()) { 1494 if (!context()->IsTest()) {
1474 __ bind(&done); 1495 __ bind(&done);
1475 } 1496 }
1476 } 1497 }
1477 1498
1478 1499
(...skipping 30 matching lines...) Expand all
1509 } else { 1530 } else {
1510 PushOperand(isolate()->factory()->the_hole_value()); 1531 PushOperand(isolate()->factory()->the_hole_value());
1511 } 1532 }
1512 1533
1513 VisitForStackValue(lit->constructor()); 1534 VisitForStackValue(lit->constructor());
1514 1535
1515 PushOperand(Smi::FromInt(lit->start_position())); 1536 PushOperand(Smi::FromInt(lit->start_position()));
1516 PushOperand(Smi::FromInt(lit->end_position())); 1537 PushOperand(Smi::FromInt(lit->end_position()));
1517 1538
1518 CallRuntimeWithOperands(Runtime::kDefineClass); 1539 CallRuntimeWithOperands(Runtime::kDefineClass);
1519 PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG); 1540 PrepareForBailoutForId(lit->CreateLiteralId(),
1541 Deoptimizer::BailoutState::TOS_REGISTER);
1520 PushOperand(result_register()); 1542 PushOperand(result_register());
1521 1543
1522 // Load the "prototype" from the constructor. 1544 // Load the "prototype" from the constructor.
1523 __ Move(LoadDescriptor::ReceiverRegister(), result_register()); 1545 __ Move(LoadDescriptor::ReceiverRegister(), result_register());
1524 __ LoadRoot(LoadDescriptor::NameRegister(), 1546 __ LoadRoot(LoadDescriptor::NameRegister(),
1525 Heap::kprototype_stringRootIndex); 1547 Heap::kprototype_stringRootIndex);
1526 __ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot())); 1548 __ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot()));
1527 CallLoadIC(NOT_INSIDE_TYPEOF); 1549 CallLoadIC(NOT_INSIDE_TYPEOF);
1528 PrepareForBailoutForId(lit->PrototypeId(), TOS_REG); 1550 PrepareForBailoutForId(lit->PrototypeId(),
1551 Deoptimizer::BailoutState::TOS_REGISTER);
1529 PushOperand(result_register()); 1552 PushOperand(result_register());
1530 1553
1531 EmitClassDefineProperties(lit); 1554 EmitClassDefineProperties(lit);
1532 DropOperands(1); 1555 DropOperands(1);
1533 1556
1534 // Set the constructor to have fast properties. 1557 // Set the constructor to have fast properties.
1535 CallRuntimeWithOperands(Runtime::kToFastProperties); 1558 CallRuntimeWithOperands(Runtime::kToFastProperties);
1536 1559
1537 if (lit->class_variable_proxy() != nullptr) { 1560 if (lit->class_variable_proxy() != nullptr) {
1538 EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT, 1561 EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT,
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 1682
1660 if (expr->is_jsruntime()) { 1683 if (expr->is_jsruntime()) {
1661 Comment cmnt(masm_, "[ CallRuntime"); 1684 Comment cmnt(masm_, "[ CallRuntime");
1662 EmitLoadJSRuntimeFunction(expr); 1685 EmitLoadJSRuntimeFunction(expr);
1663 1686
1664 // Push the arguments ("left-to-right"). 1687 // Push the arguments ("left-to-right").
1665 for (int i = 0; i < arg_count; i++) { 1688 for (int i = 0; i < arg_count; i++) {
1666 VisitForStackValue(args->at(i)); 1689 VisitForStackValue(args->at(i));
1667 } 1690 }
1668 1691
1669 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); 1692 PrepareForBailoutForId(expr->CallId(),
1693 Deoptimizer::BailoutState::NO_REGISTERS);
1670 EmitCallJSRuntimeFunction(expr); 1694 EmitCallJSRuntimeFunction(expr);
1671 context()->DropAndPlug(1, result_register()); 1695 context()->DropAndPlug(1, result_register());
1672 1696
1673 } else { 1697 } else {
1674 const Runtime::Function* function = expr->function(); 1698 const Runtime::Function* function = expr->function();
1675 switch (function->function_id) { 1699 switch (function->function_id) {
1676 #define CALL_INTRINSIC_GENERATOR(Name) \ 1700 #define CALL_INTRINSIC_GENERATOR(Name) \
1677 case Runtime::kInline##Name: { \ 1701 case Runtime::kInline##Name: { \
1678 Comment cmnt(masm_, "[ Inline" #Name); \ 1702 Comment cmnt(masm_, "[ Inline" #Name); \
1679 return Emit##Name(expr); \ 1703 return Emit##Name(expr); \
1680 } 1704 }
1681 FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR) 1705 FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
1682 #undef CALL_INTRINSIC_GENERATOR 1706 #undef CALL_INTRINSIC_GENERATOR
1683 default: { 1707 default: {
1684 Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic"); 1708 Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
1685 // Push the arguments ("left-to-right"). 1709 // Push the arguments ("left-to-right").
1686 for (int i = 0; i < arg_count; i++) { 1710 for (int i = 0; i < arg_count; i++) {
1687 VisitForStackValue(args->at(i)); 1711 VisitForStackValue(args->at(i));
1688 } 1712 }
1689 1713
1690 // Call the C runtime function. 1714 // Call the C runtime function.
1691 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); 1715 PrepareForBailoutForId(expr->CallId(),
1716 Deoptimizer::BailoutState::NO_REGISTERS);
1692 __ CallRuntime(expr->function(), arg_count); 1717 __ CallRuntime(expr->function(), arg_count);
1693 OperandStackDepthDecrement(arg_count); 1718 OperandStackDepthDecrement(arg_count);
1694 context()->Plug(result_register()); 1719 context()->Plug(result_register());
1695 } 1720 }
1696 } 1721 }
1697 } 1722 }
1698 } 1723 }
1699 1724
1700 void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 1725 void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
1701 1726
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1870 #endif // DEBUG 1895 #endif // DEBUG
1871 1896
1872 1897
1873 FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded( 1898 FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
1874 FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id, 1899 FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id,
1875 BailoutId declarations_id, BailoutId exit_id) 1900 BailoutId declarations_id, BailoutId exit_id)
1876 : codegen_(codegen), exit_id_(exit_id) { 1901 : codegen_(codegen), exit_id_(exit_id) {
1877 saved_scope_ = codegen_->scope(); 1902 saved_scope_ = codegen_->scope();
1878 1903
1879 if (scope == NULL) { 1904 if (scope == NULL) {
1880 codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS); 1905 codegen_->PrepareForBailoutForId(entry_id,
1906 Deoptimizer::BailoutState::NO_REGISTERS);
1881 needs_block_context_ = false; 1907 needs_block_context_ = false;
1882 } else { 1908 } else {
1883 needs_block_context_ = scope->NeedsContext(); 1909 needs_block_context_ = scope->NeedsContext();
1884 codegen_->scope_ = scope; 1910 codegen_->scope_ = scope;
1885 { 1911 {
1886 if (needs_block_context_) { 1912 if (needs_block_context_) {
1887 Comment cmnt(masm(), "[ Extend block context"); 1913 Comment cmnt(masm(), "[ Extend block context");
1888 codegen_->PushOperand(scope->GetScopeInfo(codegen->isolate())); 1914 codegen_->PushOperand(scope->GetScopeInfo(codegen->isolate()));
1889 codegen_->PushFunctionArgumentForContextAllocation(); 1915 codegen_->PushFunctionArgumentForContextAllocation();
1890 codegen_->CallRuntimeWithOperands(Runtime::kPushBlockContext); 1916 codegen_->CallRuntimeWithOperands(Runtime::kPushBlockContext);
1891 1917
1892 // Replace the context stored in the frame. 1918 // Replace the context stored in the frame.
1893 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, 1919 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1894 codegen_->context_register()); 1920 codegen_->context_register());
1895 } 1921 }
1896 CHECK_EQ(0, scope->num_stack_slots()); 1922 CHECK_EQ(0, scope->num_stack_slots());
1897 codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS); 1923 codegen_->PrepareForBailoutForId(entry_id,
1924 Deoptimizer::BailoutState::NO_REGISTERS);
1898 } 1925 }
1899 { 1926 {
1900 Comment cmnt(masm(), "[ Declarations"); 1927 Comment cmnt(masm(), "[ Declarations");
1901 codegen_->VisitDeclarations(scope->declarations()); 1928 codegen_->VisitDeclarations(scope->declarations());
1902 codegen_->PrepareForBailoutForId(declarations_id, NO_REGISTERS); 1929 codegen_->PrepareForBailoutForId(declarations_id,
1930 Deoptimizer::BailoutState::NO_REGISTERS);
1903 } 1931 }
1904 } 1932 }
1905 } 1933 }
1906 1934
1907 1935
1908 FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() { 1936 FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() {
1909 if (needs_block_context_) { 1937 if (needs_block_context_) {
1910 codegen_->LoadContextField(codegen_->context_register(), 1938 codegen_->LoadContextField(codegen_->context_register(),
1911 Context::PREVIOUS_INDEX); 1939 Context::PREVIOUS_INDEX);
1912 // Update local stack frame context field. 1940 // Update local stack frame context field.
1913 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, 1941 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1914 codegen_->context_register()); 1942 codegen_->context_register());
1915 } 1943 }
1916 codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS); 1944 codegen_->PrepareForBailoutForId(exit_id_,
1945 Deoptimizer::BailoutState::NO_REGISTERS);
1917 codegen_->scope_ = saved_scope_; 1946 codegen_->scope_ = saved_scope_;
1918 } 1947 }
1919 1948
1920 1949
1921 bool FullCodeGenerator::NeedsHoleCheckForLoad(VariableProxy* proxy) { 1950 bool FullCodeGenerator::NeedsHoleCheckForLoad(VariableProxy* proxy) {
1922 Variable* var = proxy->var(); 1951 Variable* var = proxy->var();
1923 1952
1924 if (!var->binding_needs_init()) { 1953 if (!var->binding_needs_init()) {
1925 return false; 1954 return false;
1926 } 1955 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1975 return var->scope()->is_nonlinear() || 2004 return var->scope()->is_nonlinear() ||
1976 var->initializer_position() >= proxy->position(); 2005 var->initializer_position() >= proxy->position();
1977 } 2006 }
1978 2007
1979 2008
1980 #undef __ 2009 #undef __
1981 2010
1982 2011
1983 } // namespace internal 2012 } // namespace internal
1984 } // namespace v8 2013 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698