OLD | NEW |
---|---|
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 17 matching lines...) Expand all Loading... | |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" |
31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
32 #include "debug.h" | 32 #include "debug.h" |
33 #include "scopes.h" | 33 #include "scopes.h" |
34 #include "runtime.h" | 34 #include "runtime.h" |
35 | 35 |
36 namespace v8 { namespace internal { | 36 namespace v8 { namespace internal { |
37 | 37 |
38 #define __ masm_-> | |
39 | |
40 // ------------------------------------------------------------------------- | |
41 // VirtualFrame implementation. | |
42 | |
43 VirtualFrame::VirtualFrame(CodeGenerator* cgen) { | |
44 ASSERT(cgen->scope() != NULL); | |
45 | |
46 masm_ = cgen->masm(); | |
47 frame_local_count_ = cgen->scope()->num_stack_slots(); | |
48 parameter_count_ = cgen->scope()->num_parameters(); | |
49 } | |
50 | |
51 | |
38 // ------------------------------------------------------------------------- | 52 // ------------------------------------------------------------------------- |
39 // CodeGenState implementation. | 53 // CodeGenState implementation. |
40 | 54 |
41 CodeGenState::CodeGenState(CodeGenerator* owner) | 55 CodeGenState::CodeGenState(CodeGenerator* owner) |
42 : owner_(owner), | 56 : owner_(owner), |
43 typeof_state_(NOT_INSIDE_TYPEOF), | 57 typeof_state_(NOT_INSIDE_TYPEOF), |
44 true_target_(NULL), | 58 true_target_(NULL), |
45 false_target_(NULL), | 59 false_target_(NULL), |
46 previous_(NULL) { | 60 previous_(NULL) { |
47 owner_->set_state(this); | 61 owner_->set_state(this); |
(...skipping 12 matching lines...) Expand all Loading... | |
60 owner_->set_state(this); | 74 owner_->set_state(this); |
61 } | 75 } |
62 | 76 |
63 | 77 |
64 CodeGenState::~CodeGenState() { | 78 CodeGenState::~CodeGenState() { |
65 ASSERT(owner_->state() == this); | 79 ASSERT(owner_->state() == this); |
66 owner_->set_state(previous_); | 80 owner_->set_state(previous_); |
67 } | 81 } |
68 | 82 |
69 | 83 |
70 // ----------------------------------------------------------------------------- | 84 // ------------------------------------------------------------------------- |
71 // CodeGenerator implementation | 85 // CodeGenerator implementation |
72 | 86 |
73 #define __ masm_-> | |
74 | |
75 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, | 87 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, |
76 bool is_eval) | 88 bool is_eval) |
77 : is_eval_(is_eval), | 89 : is_eval_(is_eval), |
78 script_(script), | 90 script_(script), |
79 deferred_(8), | 91 deferred_(8), |
80 masm_(new MacroAssembler(NULL, buffer_size)), | 92 masm_(new MacroAssembler(NULL, buffer_size)), |
81 scope_(NULL), | 93 scope_(NULL), |
94 frame_(NULL), | |
82 cc_reg_(al), | 95 cc_reg_(al), |
83 state_(NULL), | 96 state_(NULL), |
84 break_stack_height_(0) { | 97 break_stack_height_(0) { |
85 } | 98 } |
86 | 99 |
87 | 100 |
88 // Calling conventions: | 101 // Calling conventions: |
89 | 102 |
90 // r0: the number of arguments | 103 // r0: the number of arguments |
91 // fp: frame pointer | 104 // fp: frame pointer |
92 // sp: stack pointer | 105 // sp: stack pointer |
93 // pp: caller's parameter pointer | 106 // pp: caller's parameter pointer |
94 // cp: callee's context | 107 // cp: callee's context |
95 | 108 |
96 void CodeGenerator::GenCode(FunctionLiteral* fun) { | 109 void CodeGenerator::GenCode(FunctionLiteral* fun) { |
97 Scope* scope = fun->scope(); | |
98 ZoneList<Statement*>* body = fun->body(); | 110 ZoneList<Statement*>* body = fun->body(); |
99 | 111 |
100 // Initialize state. | 112 // Initialize state. |
101 { CodeGenState state(this); | 113 ASSERT(scope_ == NULL); |
102 scope_ = scope; | 114 scope_ = fun->scope(); |
103 cc_reg_ = al; | 115 ASSERT(frame_ == NULL); |
116 VirtualFrame virtual_frame(this); | |
117 frame_ = &virtual_frame; | |
118 cc_reg_ = al; | |
119 { | |
120 CodeGenState state(this); | |
104 | 121 |
105 // Entry | 122 // Entry |
106 // stack: function, receiver, arguments, return address | 123 // stack: function, receiver, arguments, return address |
107 // r0: number of arguments | 124 // r0: number of arguments |
108 // sp: stack pointer | 125 // sp: stack pointer |
109 // fp: frame pointer | 126 // fp: frame pointer |
110 // pp: caller's parameter pointer | 127 // pp: caller's parameter pointer |
111 // cp: callee's context | 128 // cp: callee's context |
112 | 129 |
113 { Comment cmnt(masm_, "[ enter JS frame"); | 130 { Comment cmnt(masm_, "[ enter JS frame"); |
114 EnterJSFrame(); | 131 EnterJSFrame(); |
115 } | 132 } |
116 // tos: code slot | 133 // tos: code slot |
117 #ifdef DEBUG | 134 #ifdef DEBUG |
118 if (strlen(FLAG_stop_at) > 0 && | 135 if (strlen(FLAG_stop_at) > 0 && |
119 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 136 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
120 __ stop("stop-at"); | 137 __ stop("stop-at"); |
121 } | 138 } |
122 #endif | 139 #endif |
123 | 140 |
124 // Allocate space for locals and initialize them. | 141 // Allocate space for locals and initialize them. |
125 if (scope->num_stack_slots() > 0) { | 142 if (scope_->num_stack_slots() > 0) { |
126 Comment cmnt(masm_, "[ allocate space for locals"); | 143 Comment cmnt(masm_, "[ allocate space for locals"); |
127 // Initialize stack slots with 'undefined' value. | 144 // Initialize stack slots with 'undefined' value. |
128 __ mov(ip, Operand(Factory::undefined_value())); | 145 __ mov(ip, Operand(Factory::undefined_value())); |
129 for (int i = 0; i < scope->num_stack_slots(); i++) { | 146 for (int i = 0; i < scope_->num_stack_slots(); i++) { |
130 __ push(ip); | 147 __ push(ip); |
131 } | 148 } |
132 } | 149 } |
133 | 150 |
134 if (scope->num_heap_slots() > 0) { | 151 if (scope_->num_heap_slots() > 0) { |
135 // Allocate local context. | 152 // Allocate local context. |
136 // Get outer context and create a new context based on it. | 153 // Get outer context and create a new context based on it. |
137 __ ldr(r0, FunctionOperand()); | 154 __ ldr(r0, frame_->Function()); |
138 __ push(r0); | 155 __ push(r0); |
139 __ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result | 156 __ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result |
140 | 157 |
141 if (kDebug) { | 158 if (kDebug) { |
142 Label verified_true; | 159 Label verified_true; |
143 __ cmp(r0, Operand(cp)); | 160 __ cmp(r0, Operand(cp)); |
144 __ b(eq, &verified_true); | 161 __ b(eq, &verified_true); |
145 __ stop("NewContext: r0 is expected to be the same as cp"); | 162 __ stop("NewContext: r0 is expected to be the same as cp"); |
146 __ bind(&verified_true); | 163 __ bind(&verified_true); |
147 } | 164 } |
148 // Update context local. | 165 // Update context local. |
149 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 166 __ str(cp, frame_->Context()); |
150 } | 167 } |
151 | 168 |
152 // TODO(1241774): Improve this code!!! | 169 // TODO(1241774): Improve this code!!! |
153 // 1) only needed if we have a context | 170 // 1) only needed if we have a context |
154 // 2) no need to recompute context ptr every single time | 171 // 2) no need to recompute context ptr every single time |
155 // 3) don't copy parameter operand code from SlotOperand! | 172 // 3) don't copy parameter operand code from SlotOperand! |
156 { | 173 { |
157 Comment cmnt2(masm_, "[ copy context parameters into .context"); | 174 Comment cmnt2(masm_, "[ copy context parameters into .context"); |
158 | 175 |
159 // Note that iteration order is relevant here! If we have the same | 176 // Note that iteration order is relevant here! If we have the same |
160 // parameter twice (e.g., function (x, y, x)), and that parameter | 177 // parameter twice (e.g., function (x, y, x)), and that parameter |
161 // needs to be copied into the context, it must be the last argument | 178 // needs to be copied into the context, it must be the last argument |
162 // passed to the parameter that needs to be copied. This is a rare | 179 // passed to the parameter that needs to be copied. This is a rare |
163 // case so we don't check for it, instead we rely on the copying | 180 // case so we don't check for it, instead we rely on the copying |
164 // order: such a parameter is copied repeatedly into the same | 181 // order: such a parameter is copied repeatedly into the same |
165 // context location and thus the last value is what is seen inside | 182 // context location and thus the last value is what is seen inside |
166 // the function. | 183 // the function. |
167 for (int i = 0; i < scope->num_parameters(); i++) { | 184 for (int i = 0; i < scope_->num_parameters(); i++) { |
168 Variable* par = scope->parameter(i); | 185 Variable* par = scope_->parameter(i); |
169 Slot* slot = par->slot(); | 186 Slot* slot = par->slot(); |
170 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 187 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
171 ASSERT(!scope->is_global_scope()); // no parameters in global scope | 188 ASSERT(!scope_->is_global_scope()); // no parameters in global scope |
172 __ ldr(r1, ParameterOperand(i)); | 189 __ ldr(r1, frame_->Parameter(i)); |
173 // Loads r2 with context; used below in RecordWrite. | 190 // Loads r2 with context; used below in RecordWrite. |
174 __ str(r1, SlotOperand(slot, r2)); | 191 __ str(r1, SlotOperand(slot, r2)); |
175 // Load the offset into r3. | 192 // Load the offset into r3. |
176 int slot_offset = | 193 int slot_offset = |
177 FixedArray::kHeaderSize + slot->index() * kPointerSize; | 194 FixedArray::kHeaderSize + slot->index() * kPointerSize; |
178 __ mov(r3, Operand(slot_offset)); | 195 __ mov(r3, Operand(slot_offset)); |
179 __ RecordWrite(r2, r3, r1); | 196 __ RecordWrite(r2, r3, r1); |
180 } | 197 } |
181 } | 198 } |
182 } | 199 } |
183 | 200 |
184 // Store the arguments object. | 201 // Store the arguments object. |
185 // This must happen after context initialization because | 202 // This must happen after context initialization because |
186 // the arguments array may be stored in the context! | 203 // the arguments array may be stored in the context! |
187 if (scope->arguments() != NULL) { | 204 if (scope_->arguments() != NULL) { |
188 ASSERT(scope->arguments_shadow() != NULL); | 205 ASSERT(scope_->arguments_shadow() != NULL); |
189 Comment cmnt(masm_, "[ allocate arguments object"); | 206 Comment cmnt(masm_, "[ allocate arguments object"); |
190 { Reference shadow_ref(this, scope->arguments_shadow()); | 207 { Reference shadow_ref(this, scope_->arguments_shadow()); |
191 { Reference arguments_ref(this, scope->arguments()); | 208 { Reference arguments_ref(this, scope_->arguments()); |
192 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 209 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
193 __ ldr(r2, FunctionOperand()); | 210 __ ldr(r2, frame_->Function()); |
194 // The receiver is below the arguments, the return address, | 211 // The receiver is below the arguments, the return address, |
195 // and the frame pointer on the stack. | 212 // and the frame pointer on the stack. |
196 const int kReceiverDisplacement = 2 + scope->num_parameters(); | 213 const int kReceiverDisplacement = 2 + scope_->num_parameters(); |
197 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize)); | 214 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize)); |
198 __ mov(r0, Operand(Smi::FromInt(scope->num_parameters()))); | 215 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); |
199 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); | 216 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); |
200 __ CallStub(&stub); | 217 __ CallStub(&stub); |
Kevin Millikin (Chromium)
2008/11/04 08:39:59
This is the only place that "ReceiverOperand" woul
| |
201 __ push(r0); | 218 __ push(r0); |
202 arguments_ref.SetValue(NOT_CONST_INIT); | 219 arguments_ref.SetValue(NOT_CONST_INIT); |
203 } | 220 } |
204 shadow_ref.SetValue(NOT_CONST_INIT); | 221 shadow_ref.SetValue(NOT_CONST_INIT); |
205 } | 222 } |
206 __ pop(r0); // Value is no longer needed. | 223 __ pop(r0); // Value is no longer needed. |
207 } | 224 } |
208 | 225 |
209 // Generate code to 'execute' declarations and initialize | 226 // Generate code to 'execute' declarations and initialize |
210 // functions (source elements). In case of an illegal | 227 // functions (source elements). In case of an illegal |
211 // redeclaration we need to handle that instead of processing the | 228 // redeclaration we need to handle that instead of processing the |
212 // declarations. | 229 // declarations. |
213 if (scope->HasIllegalRedeclaration()) { | 230 if (scope_->HasIllegalRedeclaration()) { |
214 Comment cmnt(masm_, "[ illegal redeclarations"); | 231 Comment cmnt(masm_, "[ illegal redeclarations"); |
215 scope->VisitIllegalRedeclaration(this); | 232 scope_->VisitIllegalRedeclaration(this); |
216 } else { | 233 } else { |
217 Comment cmnt(masm_, "[ declarations"); | 234 Comment cmnt(masm_, "[ declarations"); |
218 // ProcessDeclarations calls DeclareGlobals indirectly | 235 // ProcessDeclarations calls DeclareGlobals indirectly |
219 ProcessDeclarations(scope->declarations()); | 236 ProcessDeclarations(scope_->declarations()); |
220 | 237 |
221 // Bail out if a stack-overflow exception occurred when | 238 // Bail out if a stack-overflow exception occurred when |
222 // processing declarations. | 239 // processing declarations. |
223 if (HasStackOverflow()) return; | 240 if (HasStackOverflow()) return; |
224 } | 241 } |
225 | 242 |
226 if (FLAG_trace) { | 243 if (FLAG_trace) { |
227 // Push a valid value as the parameter. The runtime call only uses | 244 // Push a valid value as the parameter. The runtime call only uses |
228 // it as the return value to indicate non-failure. | 245 // it as the return value to indicate non-failure. |
229 __ CallRuntime(Runtime::kTraceEnter, 0); | 246 __ CallRuntime(Runtime::kTraceEnter, 0); |
230 } | 247 } |
231 CheckStack(); | 248 CheckStack(); |
232 | 249 |
233 // Compile the body of the function in a vanilla state. Don't | 250 // Compile the body of the function in a vanilla state. Don't |
234 // bother compiling all the code if the scope has an illegal | 251 // bother compiling all the code if the scope has an illegal |
235 // redeclaration. | 252 // redeclaration. |
236 if (!scope->HasIllegalRedeclaration()) { | 253 if (!scope_->HasIllegalRedeclaration()) { |
237 Comment cmnt(masm_, "[ function body"); | 254 Comment cmnt(masm_, "[ function body"); |
238 #ifdef DEBUG | 255 #ifdef DEBUG |
239 bool is_builtin = Bootstrapper::IsActive(); | 256 bool is_builtin = Bootstrapper::IsActive(); |
240 bool should_trace = | 257 bool should_trace = |
241 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; | 258 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
242 if (should_trace) { | 259 if (should_trace) { |
243 __ CallRuntime(Runtime::kDebugTrace, 0); | 260 __ CallRuntime(Runtime::kDebugTrace, 0); |
244 } | 261 } |
245 #endif | 262 #endif |
246 VisitStatements(body); | 263 VisitStatements(body); |
(...skipping 18 matching lines...) Expand all Loading... | |
265 | 282 |
266 // Tear down the frame which will restore the caller's frame pointer and the | 283 // Tear down the frame which will restore the caller's frame pointer and the |
267 // link register. | 284 // link register. |
268 ExitJSFrame(); | 285 ExitJSFrame(); |
269 | 286 |
270 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); | 287 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); |
271 __ mov(pc, lr); | 288 __ mov(pc, lr); |
272 | 289 |
273 // Code generation state must be reset. | 290 // Code generation state must be reset. |
274 scope_ = NULL; | 291 scope_ = NULL; |
292 frame_ = NULL; | |
275 ASSERT(!has_cc()); | 293 ASSERT(!has_cc()); |
276 ASSERT(state_ == NULL); | 294 ASSERT(state_ == NULL); |
277 } | 295 } |
278 | 296 |
279 | 297 |
280 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { | 298 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { |
281 // Currently, this assertion will fail if we try to assign to | 299 // Currently, this assertion will fail if we try to assign to |
282 // a constant variable that is constant because it is read-only | 300 // a constant variable that is constant because it is read-only |
283 // (such as the variable referring to a named function expression). | 301 // (such as the variable referring to a named function expression). |
284 // We need to implement assignments to read-only variables. | 302 // We need to implement assignments to read-only variables. |
285 // Ideally, we should do this during AST generation (by converting | 303 // Ideally, we should do this during AST generation (by converting |
286 // such assignments into expression statements); however, in general | 304 // such assignments into expression statements); however, in general |
287 // we may not be able to make the decision until past AST generation, | 305 // we may not be able to make the decision until past AST generation, |
288 // that is when the entire program is known. | 306 // that is when the entire program is known. |
289 ASSERT(slot != NULL); | 307 ASSERT(slot != NULL); |
290 int index = slot->index(); | 308 int index = slot->index(); |
291 switch (slot->type()) { | 309 switch (slot->type()) { |
292 case Slot::PARAMETER: | 310 case Slot::PARAMETER: |
293 return ParameterOperand(index); | 311 return frame_->Parameter(index); |
294 | 312 |
295 case Slot::LOCAL: { | 313 case Slot::LOCAL: |
296 ASSERT(0 <= index && index < scope()->num_stack_slots()); | 314 return frame_->Local(index); |
297 const int kLocalOffset = JavaScriptFrameConstants::kLocal0Offset; | |
298 return MemOperand(fp, kLocalOffset - index * kPointerSize); | |
299 } | |
300 | 315 |
301 case Slot::CONTEXT: { | 316 case Slot::CONTEXT: { |
302 // Follow the context chain if necessary. | 317 // Follow the context chain if necessary. |
303 ASSERT(!tmp.is(cp)); // do not overwrite context register | 318 ASSERT(!tmp.is(cp)); // do not overwrite context register |
304 Register context = cp; | 319 Register context = cp; |
305 int chain_length = scope()->ContextChainLength(slot->var()->scope()); | 320 int chain_length = scope()->ContextChainLength(slot->var()->scope()); |
306 for (int i = chain_length; i-- > 0;) { | 321 for (int i = chain_length; i-- > 0;) { |
307 // Load the closure. | 322 // Load the closure. |
308 // (All contexts, even 'with' contexts, have a closure, | 323 // (All contexts, even 'with' contexts, have a closure, |
309 // and it is the same for all contexts inside a function. | 324 // and it is the same for all contexts inside a function. |
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
972 } | 987 } |
973 | 988 |
974 // Record the position for debugging purposes. | 989 // Record the position for debugging purposes. |
975 __ RecordPosition(position); | 990 __ RecordPosition(position); |
976 | 991 |
977 // Use the shared code stub to call the function. | 992 // Use the shared code stub to call the function. |
978 CallFunctionStub call_function(args->length()); | 993 CallFunctionStub call_function(args->length()); |
979 __ CallStub(&call_function); | 994 __ CallStub(&call_function); |
980 | 995 |
981 // Restore context and pop function from the stack. | 996 // Restore context and pop function from the stack. |
982 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 997 __ ldr(cp, frame_->Context()); |
983 __ pop(); // discard the TOS | 998 __ pop(); // discard the TOS |
984 } | 999 } |
985 | 1000 |
986 | 1001 |
987 void CodeGenerator::Branch(bool if_true, Label* L) { | 1002 void CodeGenerator::Branch(bool if_true, Label* L) { |
988 ASSERT(has_cc()); | 1003 ASSERT(has_cc()); |
989 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); | 1004 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); |
990 __ b(cc, L); | 1005 __ b(cc, L); |
991 cc_reg_ = al; | 1006 cc_reg_ = al; |
992 } | 1007 } |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 Load(node->expression()); | 1222 Load(node->expression()); |
1208 __ CallRuntime(Runtime::kPushContext, 1); | 1223 __ CallRuntime(Runtime::kPushContext, 1); |
1209 if (kDebug) { | 1224 if (kDebug) { |
1210 Label verified_true; | 1225 Label verified_true; |
1211 __ cmp(r0, Operand(cp)); | 1226 __ cmp(r0, Operand(cp)); |
1212 __ b(eq, &verified_true); | 1227 __ b(eq, &verified_true); |
1213 __ stop("PushContext: r0 is expected to be the same as cp"); | 1228 __ stop("PushContext: r0 is expected to be the same as cp"); |
1214 __ bind(&verified_true); | 1229 __ bind(&verified_true); |
1215 } | 1230 } |
1216 // Update context local. | 1231 // Update context local. |
1217 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1232 __ str(cp, frame_->Context()); |
1218 } | 1233 } |
1219 | 1234 |
1220 | 1235 |
1221 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 1236 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
1222 Comment cmnt(masm_, "[ WithExitStatement"); | 1237 Comment cmnt(masm_, "[ WithExitStatement"); |
1223 // Pop context. | 1238 // Pop context. |
1224 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); | 1239 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); |
1225 // Update context local. | 1240 // Update context local. |
1226 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1241 __ str(cp, frame_->Context()); |
1227 } | 1242 } |
1228 | 1243 |
1229 | 1244 |
1230 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { | 1245 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { |
1231 return kFastSwitchMaxOverheadFactor; | 1246 return kFastSwitchMaxOverheadFactor; |
1232 } | 1247 } |
1233 | 1248 |
1234 int CodeGenerator::FastCaseSwitchMinCaseCount() { | 1249 int CodeGenerator::FastCaseSwitchMinCaseCount() { |
1235 return kFastSwitchMinCaseCount; | 1250 return kFastSwitchMinCaseCount; |
1236 } | 1251 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1317 // statements if it does not match any of the cases. | 1332 // statements if it does not match any of the cases. |
1318 __ b(&next); | 1333 __ b(&next); |
1319 | 1334 |
1320 // Bind the default case label, so we can branch to it when we | 1335 // Bind the default case label, so we can branch to it when we |
1321 // have compared against all other cases. | 1336 // have compared against all other cases. |
1322 ASSERT(default_case.is_unused()); // at most one default clause | 1337 ASSERT(default_case.is_unused()); // at most one default clause |
1323 __ bind(&default_case); | 1338 __ bind(&default_case); |
1324 } else { | 1339 } else { |
1325 __ bind(&next); | 1340 __ bind(&next); |
1326 next.Unuse(); | 1341 next.Unuse(); |
1327 __ ldr(r0, MemOperand(sp, 0)); | 1342 __ ldr(r0, frame_->Top()); |
1328 __ push(r0); // duplicate TOS | 1343 __ push(r0); // duplicate TOS |
1329 Load(clause->label()); | 1344 Load(clause->label()); |
1330 Comparison(eq, true); | 1345 Comparison(eq, true); |
1331 Branch(false, &next); | 1346 Branch(false, &next); |
1332 } | 1347 } |
1333 | 1348 |
1334 // Entering the case statement for the first time. Remove the switch value | 1349 // Entering the case statement for the first time. Remove the switch value |
1335 // from the stack. | 1350 // from the stack. |
1336 __ pop(r0); | 1351 __ pop(r0); |
1337 | 1352 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1536 __ push(r0); | 1551 __ push(r0); |
1537 | 1552 |
1538 // Condition. | 1553 // Condition. |
1539 __ bind(&entry); | 1554 __ bind(&entry); |
1540 | 1555 |
1541 // sp[0] : index | 1556 // sp[0] : index |
1542 // sp[1] : array/enum cache length | 1557 // sp[1] : array/enum cache length |
1543 // sp[2] : array or enum cache | 1558 // sp[2] : array or enum cache |
1544 // sp[3] : 0 or map | 1559 // sp[3] : 0 or map |
1545 // sp[4] : enumerable | 1560 // sp[4] : enumerable |
1546 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); // load the current count | 1561 __ ldr(r0, frame_->Element(0)); // load the current count |
1547 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); // load the length | 1562 __ ldr(r1, frame_->Element(1)); // load the length |
1548 __ cmp(r0, Operand(r1)); // compare to the array length | 1563 __ cmp(r0, Operand(r1)); // compare to the array length |
1549 __ b(hs, &cleanup); | 1564 __ b(hs, &cleanup); |
1550 | 1565 |
1551 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 1566 __ ldr(r0, frame_->Element(0)); |
1552 | 1567 |
1553 // Get the i'th entry of the array. | 1568 // Get the i'th entry of the array. |
1554 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); | 1569 __ ldr(r2, frame_->Element(2)); |
1555 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1570 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
1556 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1571 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
1557 | 1572 |
1558 // Get Map or 0. | 1573 // Get Map or 0. |
1559 __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); | 1574 __ ldr(r2, frame_->Element(3)); |
1560 // Check if this (still) matches the map of the enumerable. | 1575 // Check if this (still) matches the map of the enumerable. |
1561 // If not, we have to filter the key. | 1576 // If not, we have to filter the key. |
1562 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); | 1577 __ ldr(r1, frame_->Element(4)); |
1563 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1578 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
1564 __ cmp(r1, Operand(r2)); | 1579 __ cmp(r1, Operand(r2)); |
1565 __ b(eq, &end_del_check); | 1580 __ b(eq, &end_del_check); |
1566 | 1581 |
1567 // Convert the entry to a string (or null if it isn't a property anymore). | 1582 // Convert the entry to a string (or null if it isn't a property anymore). |
1568 __ ldr(r0, MemOperand(sp, 4 * kPointerSize)); // push enumerable | 1583 __ ldr(r0, frame_->Element(4)); // push enumerable |
1569 __ push(r0); | 1584 __ push(r0); |
1570 __ push(r3); // push entry | 1585 __ push(r3); // push entry |
1571 __ mov(r0, Operand(1)); | 1586 __ mov(r0, Operand(1)); |
1572 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); | 1587 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); |
1573 __ mov(r3, Operand(r0)); | 1588 __ mov(r3, Operand(r0)); |
1574 | 1589 |
1575 // If the property has been removed while iterating, we just skip it. | 1590 // If the property has been removed while iterating, we just skip it. |
1576 __ cmp(r3, Operand(Factory::null_value())); | 1591 __ cmp(r3, Operand(Factory::null_value())); |
1577 __ b(eq, &next); | 1592 __ b(eq, &next); |
1578 | 1593 |
1579 | 1594 |
1580 __ bind(&end_del_check); | 1595 __ bind(&end_del_check); |
1581 | 1596 |
1582 // Store the entry in the 'each' expression and take another spin in the loop. | 1597 // Store the entry in the 'each' expression and take another spin in the loop. |
1583 // r3: i'th entry of the enum cache (or string there of) | 1598 // r3: i'th entry of the enum cache (or string there of) |
1584 __ push(r3); // push entry | 1599 __ push(r3); // push entry |
1585 { Reference each(this, node->each()); | 1600 { Reference each(this, node->each()); |
1586 if (!each.is_illegal()) { | 1601 if (!each.is_illegal()) { |
1587 if (each.size() > 0) { | 1602 if (each.size() > 0) { |
1588 __ ldr(r0, MemOperand(sp, kPointerSize * each.size())); | 1603 __ ldr(r0, frame_->Element(each.size())); |
1589 __ push(r0); | 1604 __ push(r0); |
1590 } | 1605 } |
1591 // If the reference was to a slot we rely on the convenient property | 1606 // If the reference was to a slot we rely on the convenient property |
1592 // that it doesn't matter whether a value (eg, r3 pushed above) is | 1607 // that it doesn't matter whether a value (eg, r3 pushed above) is |
1593 // right on top of or right underneath a zero-sized reference. | 1608 // right on top of or right underneath a zero-sized reference. |
1594 each.SetValue(NOT_CONST_INIT); | 1609 each.SetValue(NOT_CONST_INIT); |
1595 if (each.size() > 0) { | 1610 if (each.size() > 0) { |
1596 // It's safe to pop the value lying on top of the reference before | 1611 // It's safe to pop the value lying on top of the reference before |
1597 // unloading the reference itself (which preserves the top of stack, | 1612 // unloading the reference itself (which preserves the top of stack, |
1598 // ie, now the topmost value of the non-zero sized reference), since | 1613 // ie, now the topmost value of the non-zero sized reference), since |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1673 // After shadowing stops, the original labels are unshadowed and the | 1688 // After shadowing stops, the original labels are unshadowed and the |
1674 // LabelShadows represent the formerly shadowing labels. | 1689 // LabelShadows represent the formerly shadowing labels. |
1675 int nof_unlinks = 0; | 1690 int nof_unlinks = 0; |
1676 for (int i = 0; i <= nof_escapes; i++) { | 1691 for (int i = 0; i <= nof_escapes; i++) { |
1677 shadows[i]->StopShadowing(); | 1692 shadows[i]->StopShadowing(); |
1678 if (shadows[i]->is_linked()) nof_unlinks++; | 1693 if (shadows[i]->is_linked()) nof_unlinks++; |
1679 } | 1694 } |
1680 | 1695 |
1681 // Unlink from try chain. | 1696 // Unlink from try chain. |
1682 // TOS contains code slot | 1697 // TOS contains code slot |
1683 const int kNextOffset = StackHandlerConstants::kNextOffset + | 1698 const int kNextIndex = (StackHandlerConstants::kNextOffset |
1684 StackHandlerConstants::kAddressDisplacement; | 1699 + StackHandlerConstants::kAddressDisplacement) |
1685 __ ldr(r1, MemOperand(sp, kNextOffset)); // read next_sp | 1700 / kPointerSize; |
Kevin Millikin (Chromium)
2008/11/04 08:39:59
Changed as per request.
| |
1701 __ ldr(r1, frame_->Element(kNextIndex)); // read next_sp | |
1686 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1702 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
1687 __ str(r1, MemOperand(r3)); | 1703 __ str(r1, MemOperand(r3)); |
1688 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1704 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
1689 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1705 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
1690 // Code slot popped. | 1706 // Code slot popped. |
1691 if (nof_unlinks > 0) __ b(&exit); | 1707 if (nof_unlinks > 0) __ b(&exit); |
1692 | 1708 |
1693 // Generate unlink code for the (formerly) shadowing labels that have been | 1709 // Generate unlink code for the (formerly) shadowing labels that have been |
1694 // jumped to. | 1710 // jumped to. |
1695 for (int i = 0; i <= nof_escapes; i++) { | 1711 for (int i = 0; i <= nof_escapes; i++) { |
1696 if (shadows[i]->is_linked()) { | 1712 if (shadows[i]->is_linked()) { |
1697 // Unlink from try chain; | 1713 // Unlink from try chain; |
1698 __ bind(shadows[i]); | 1714 __ bind(shadows[i]); |
1699 | 1715 |
1700 // Reload sp from the top handler, because some statements that we | 1716 // Reload sp from the top handler, because some statements that we |
1701 // break from (eg, for...in) may have left stuff on the stack. | 1717 // break from (eg, for...in) may have left stuff on the stack. |
1702 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1718 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
1703 __ ldr(sp, MemOperand(r3)); | 1719 __ ldr(sp, MemOperand(r3)); |
1704 | 1720 |
1705 __ ldr(r1, MemOperand(sp, kNextOffset)); | 1721 __ ldr(r1, frame_->Element(kNextIndex)); |
1706 __ str(r1, MemOperand(r3)); | 1722 __ str(r1, MemOperand(r3)); |
1707 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1723 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
1708 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1724 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
1709 // Code slot popped. | 1725 // Code slot popped. |
1710 | 1726 |
1711 __ b(shadows[i]->original_label()); | 1727 __ b(shadows[i]->original_label()); |
1712 } | 1728 } |
1713 } | 1729 } |
1714 | 1730 |
1715 __ bind(&exit); | 1731 __ bind(&exit); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1790 } | 1806 } |
1791 | 1807 |
1792 // Unlink from try chain; | 1808 // Unlink from try chain; |
1793 __ bind(&unlink); | 1809 __ bind(&unlink); |
1794 | 1810 |
1795 __ pop(r0); // Store TOS in r0 across stack manipulation | 1811 __ pop(r0); // Store TOS in r0 across stack manipulation |
1796 // Reload sp from the top handler, because some statements that we | 1812 // Reload sp from the top handler, because some statements that we |
1797 // break from (eg, for...in) may have left stuff on the stack. | 1813 // break from (eg, for...in) may have left stuff on the stack. |
1798 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1814 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
1799 __ ldr(sp, MemOperand(r3)); | 1815 __ ldr(sp, MemOperand(r3)); |
1800 const int kNextOffset = StackHandlerConstants::kNextOffset + | 1816 const int kNextIndex = (StackHandlerConstants::kNextOffset |
1801 StackHandlerConstants::kAddressDisplacement; | 1817 + StackHandlerConstants::kAddressDisplacement) |
1802 __ ldr(r1, MemOperand(sp, kNextOffset)); | 1818 / kPointerSize; |
1819 __ ldr(r1, frame_->Element(kNextIndex)); | |
1803 __ str(r1, MemOperand(r3)); | 1820 __ str(r1, MemOperand(r3)); |
1804 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1821 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
1805 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1822 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
1806 // Code slot popped. | 1823 // Code slot popped. |
1807 __ push(r0); | 1824 __ push(r0); |
1808 | 1825 |
1809 // --- Finally block --- | 1826 // --- Finally block --- |
1810 __ bind(&finally_block); | 1827 __ bind(&finally_block); |
1811 | 1828 |
1812 // Push the state on the stack. | 1829 // Push the state on the stack. |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1975 __ push(r0); | 1992 __ push(r0); |
1976 } | 1993 } |
1977 | 1994 |
1978 | 1995 |
1979 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 1996 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
1980 Comment cmnt(masm_, "[ RexExp Literal"); | 1997 Comment cmnt(masm_, "[ RexExp Literal"); |
1981 | 1998 |
1982 // Retrieve the literal array and check the allocated entry. | 1999 // Retrieve the literal array and check the allocated entry. |
1983 | 2000 |
1984 // Load the function of this activation. | 2001 // Load the function of this activation. |
1985 __ ldr(r1, FunctionOperand()); | 2002 __ ldr(r1, frame_->Function()); |
1986 | 2003 |
1987 // Load the literals array of the function. | 2004 // Load the literals array of the function. |
1988 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); | 2005 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); |
1989 | 2006 |
1990 // Load the literal at the ast saved index. | 2007 // Load the literal at the ast saved index. |
1991 int literal_offset = | 2008 int literal_offset = |
1992 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; | 2009 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; |
1993 __ ldr(r2, FieldMemOperand(r1, literal_offset)); | 2010 __ ldr(r2, FieldMemOperand(r1, literal_offset)); |
1994 | 2011 |
1995 Label done; | 2012 Label done; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2048 | 2065 |
2049 | 2066 |
2050 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { | 2067 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { |
2051 Comment cmnt(masm_, "[ ObjectLiteral"); | 2068 Comment cmnt(masm_, "[ ObjectLiteral"); |
2052 | 2069 |
2053 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); | 2070 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); |
2054 | 2071 |
2055 // Retrieve the literal array and check the allocated entry. | 2072 // Retrieve the literal array and check the allocated entry. |
2056 | 2073 |
2057 // Load the function of this activation. | 2074 // Load the function of this activation. |
2058 __ ldr(r1, FunctionOperand()); | 2075 __ ldr(r1, frame_->Function()); |
2059 | 2076 |
2060 // Load the literals array of the function. | 2077 // Load the literals array of the function. |
2061 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); | 2078 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); |
2062 | 2079 |
2063 // Load the literal at the ast saved index. | 2080 // Load the literal at the ast saved index. |
2064 int literal_offset = | 2081 int literal_offset = |
2065 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; | 2082 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; |
2066 __ ldr(r2, FieldMemOperand(r1, literal_offset)); | 2083 __ ldr(r2, FieldMemOperand(r1, literal_offset)); |
2067 | 2084 |
2068 // Check whether we need to materialize the object literal boilerplate. | 2085 // Check whether we need to materialize the object literal boilerplate. |
(...skipping 16 matching lines...) Expand all Loading... | |
2085 Expression* value = property->value(); | 2102 Expression* value = property->value(); |
2086 switch (property->kind()) { | 2103 switch (property->kind()) { |
2087 case ObjectLiteral::Property::CONSTANT: break; | 2104 case ObjectLiteral::Property::CONSTANT: break; |
2088 case ObjectLiteral::Property::COMPUTED: // fall through | 2105 case ObjectLiteral::Property::COMPUTED: // fall through |
2089 case ObjectLiteral::Property::PROTOTYPE: { | 2106 case ObjectLiteral::Property::PROTOTYPE: { |
2090 __ push(r0); // dup the result | 2107 __ push(r0); // dup the result |
2091 Load(key); | 2108 Load(key); |
2092 Load(value); | 2109 Load(value); |
2093 __ CallRuntime(Runtime::kSetProperty, 3); | 2110 __ CallRuntime(Runtime::kSetProperty, 3); |
2094 // restore r0 | 2111 // restore r0 |
2095 __ ldr(r0, MemOperand(sp, 0)); | 2112 __ ldr(r0, frame_->Top()); |
2096 break; | 2113 break; |
2097 } | 2114 } |
2098 case ObjectLiteral::Property::SETTER: { | 2115 case ObjectLiteral::Property::SETTER: { |
2099 __ push(r0); | 2116 __ push(r0); |
2100 Load(key); | 2117 Load(key); |
2101 __ mov(r0, Operand(Smi::FromInt(1))); | 2118 __ mov(r0, Operand(Smi::FromInt(1))); |
2102 __ push(r0); | 2119 __ push(r0); |
2103 Load(value); | 2120 Load(value); |
2104 __ CallRuntime(Runtime::kDefineAccessor, 4); | 2121 __ CallRuntime(Runtime::kDefineAccessor, 4); |
2105 __ ldr(r0, MemOperand(sp, 0)); | 2122 __ ldr(r0, frame_->Top()); |
2106 break; | 2123 break; |
2107 } | 2124 } |
2108 case ObjectLiteral::Property::GETTER: { | 2125 case ObjectLiteral::Property::GETTER: { |
2109 __ push(r0); | 2126 __ push(r0); |
2110 Load(key); | 2127 Load(key); |
2111 __ mov(r0, Operand(Smi::FromInt(0))); | 2128 __ mov(r0, Operand(Smi::FromInt(0))); |
2112 __ push(r0); | 2129 __ push(r0); |
2113 Load(value); | 2130 Load(value); |
2114 __ CallRuntime(Runtime::kDefineAccessor, 4); | 2131 __ CallRuntime(Runtime::kDefineAccessor, 4); |
2115 __ ldr(r0, MemOperand(sp, 0)); | 2132 __ ldr(r0, frame_->Top()); |
2116 break; | 2133 break; |
2117 } | 2134 } |
2118 } | 2135 } |
2119 } | 2136 } |
2120 } | 2137 } |
2121 | 2138 |
2122 | 2139 |
2123 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 2140 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
2124 Comment cmnt(masm_, "[ ArrayLiteral"); | 2141 Comment cmnt(masm_, "[ ArrayLiteral"); |
2125 | 2142 |
2126 // Call runtime to create the array literal. | 2143 // Call runtime to create the array literal. |
2127 __ mov(r0, Operand(node->literals())); | 2144 __ mov(r0, Operand(node->literals())); |
2128 __ push(r0); | 2145 __ push(r0); |
2129 // Load the function of this frame. | 2146 // Load the function of this frame. |
2130 __ ldr(r0, FunctionOperand()); | 2147 __ ldr(r0, frame_->Function()); |
2131 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 2148 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
2132 __ push(r0); | 2149 __ push(r0); |
2133 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); | 2150 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); |
2134 | 2151 |
2135 // Push the resulting array literal on the stack. | 2152 // Push the resulting array literal on the stack. |
2136 __ push(r0); | 2153 __ push(r0); |
2137 | 2154 |
2138 // Generate code to set the elements in the array that are not | 2155 // Generate code to set the elements in the array that are not |
2139 // literals. | 2156 // literals. |
2140 for (int i = 0; i < node->values()->length(); i++) { | 2157 for (int i = 0; i < node->values()->length(); i++) { |
2141 Expression* value = node->values()->at(i); | 2158 Expression* value = node->values()->at(i); |
2142 | 2159 |
2143 // If value is literal the property value is already | 2160 // If value is literal the property value is already |
2144 // set in the boilerplate object. | 2161 // set in the boilerplate object. |
2145 if (value->AsLiteral() == NULL) { | 2162 if (value->AsLiteral() == NULL) { |
2146 // The property must be set by generated code. | 2163 // The property must be set by generated code. |
2147 Load(value); | 2164 Load(value); |
2148 __ pop(r0); | 2165 __ pop(r0); |
2149 | 2166 |
2150 // Fetch the object literal | 2167 // Fetch the object literal |
2151 __ ldr(r1, MemOperand(sp, 0)); | 2168 __ ldr(r1, frame_->Top()); |
2152 // Get the elements array. | 2169 // Get the elements array. |
2153 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 2170 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
2154 | 2171 |
2155 // Write to the indexed properties array. | 2172 // Write to the indexed properties array. |
2156 int offset = i * kPointerSize + Array::kHeaderSize; | 2173 int offset = i * kPointerSize + Array::kHeaderSize; |
2157 __ str(r0, FieldMemOperand(r1, offset)); | 2174 __ str(r0, FieldMemOperand(r1, offset)); |
2158 | 2175 |
2159 // Update the write barrier for the array address. | 2176 // Update the write barrier for the array address. |
2160 __ mov(r3, Operand(offset)); | 2177 __ mov(r3, Operand(offset)); |
2161 __ RecordWrite(r1, r3, r2); | 2178 __ RecordWrite(r1, r3, r2); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2264 // invoked function. | 2281 // invoked function. |
2265 LoadGlobal(); | 2282 LoadGlobal(); |
2266 | 2283 |
2267 // Load the arguments. | 2284 // Load the arguments. |
2268 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2285 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2269 | 2286 |
2270 // Setup the receiver register and call the IC initialization code. | 2287 // Setup the receiver register and call the IC initialization code. |
2271 Handle<Code> stub = ComputeCallInitialize(args->length()); | 2288 Handle<Code> stub = ComputeCallInitialize(args->length()); |
2272 __ RecordPosition(node->position()); | 2289 __ RecordPosition(node->position()); |
2273 __ Call(stub, RelocInfo::CODE_TARGET_CONTEXT); | 2290 __ Call(stub, RelocInfo::CODE_TARGET_CONTEXT); |
2274 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2291 __ ldr(cp, frame_->Context()); |
2275 // Remove the function from the stack. | 2292 // Remove the function from the stack. |
2276 __ pop(); | 2293 __ pop(); |
2277 __ push(r0); | 2294 __ push(r0); |
2278 | 2295 |
2279 } else if (var != NULL && var->slot() != NULL && | 2296 } else if (var != NULL && var->slot() != NULL && |
2280 var->slot()->type() == Slot::LOOKUP) { | 2297 var->slot()->type() == Slot::LOOKUP) { |
2281 // ---------------------------------- | 2298 // ---------------------------------- |
2282 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj | 2299 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj |
2283 // ---------------------------------- | 2300 // ---------------------------------- |
2284 | 2301 |
(...skipping 26 matching lines...) Expand all Loading... | |
2311 __ push(r0); | 2328 __ push(r0); |
2312 Load(property->obj()); | 2329 Load(property->obj()); |
2313 | 2330 |
2314 // Load the arguments. | 2331 // Load the arguments. |
2315 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2332 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2316 | 2333 |
2317 // Set the receiver register and call the IC initialization code. | 2334 // Set the receiver register and call the IC initialization code. |
2318 Handle<Code> stub = ComputeCallInitialize(args->length()); | 2335 Handle<Code> stub = ComputeCallInitialize(args->length()); |
2319 __ RecordPosition(node->position()); | 2336 __ RecordPosition(node->position()); |
2320 __ Call(stub, RelocInfo::CODE_TARGET); | 2337 __ Call(stub, RelocInfo::CODE_TARGET); |
2321 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2338 __ ldr(cp, frame_->Context()); |
2322 | 2339 |
2323 // Remove the function from the stack. | 2340 // Remove the function from the stack. |
2324 __ pop(); | 2341 __ pop(); |
2325 | 2342 |
2326 __ push(r0); // push after get rid of function from the stack | 2343 __ push(r0); // push after get rid of function from the stack |
2327 | 2344 |
2328 } else { | 2345 } else { |
2329 // ------------------------------------------- | 2346 // ------------------------------------------- |
2330 // JavaScript example: 'array[index](1, 2, 3)' | 2347 // JavaScript example: 'array[index](1, 2, 3)' |
2331 // ------------------------------------------- | 2348 // ------------------------------------------- |
2332 | 2349 |
2333 // Load the function to call from the property through a reference. | 2350 // Load the function to call from the property through a reference. |
2334 Reference ref(this, property); | 2351 Reference ref(this, property); |
2335 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver | 2352 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver |
2336 | 2353 |
2337 // Pass receiver to called function. | 2354 // Pass receiver to called function. |
2338 __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize)); | 2355 __ ldr(r0, frame_->Element(ref.size())); |
2339 __ push(r0); | 2356 __ push(r0); |
2340 // Call the function. | 2357 // Call the function. |
2341 CallWithArguments(args, node->position()); | 2358 CallWithArguments(args, node->position()); |
2342 __ push(r0); | 2359 __ push(r0); |
2343 } | 2360 } |
2344 | 2361 |
2345 } else { | 2362 } else { |
2346 // ---------------------------------- | 2363 // ---------------------------------- |
2347 // JavaScript example: 'foo(1, 2, 3)' // foo is not global | 2364 // JavaScript example: 'foo(1, 2, 3)' // foo is not global |
2348 // ---------------------------------- | 2365 // ---------------------------------- |
(...skipping 27 matching lines...) Expand all Loading... | |
2376 LoadGlobal(); | 2393 LoadGlobal(); |
2377 | 2394 |
2378 // Push the arguments ("left-to-right") on the stack. | 2395 // Push the arguments ("left-to-right") on the stack. |
2379 ZoneList<Expression*>* args = node->arguments(); | 2396 ZoneList<Expression*>* args = node->arguments(); |
2380 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2397 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2381 | 2398 |
2382 // r0: the number of arguments. | 2399 // r0: the number of arguments. |
2383 __ mov(r0, Operand(args->length())); | 2400 __ mov(r0, Operand(args->length())); |
2384 | 2401 |
2385 // Load the function into r1 as per calling convention. | 2402 // Load the function into r1 as per calling convention. |
2386 __ ldr(r1, MemOperand(sp, (args->length() + 1) * kPointerSize)); | 2403 __ ldr(r1, frame_->Element(args->length() + 1)); |
2387 | 2404 |
2388 // Call the construct call builtin that handles allocation and | 2405 // Call the construct call builtin that handles allocation and |
2389 // constructor invocation. | 2406 // constructor invocation. |
2390 __ RecordPosition(RelocInfo::POSITION); | 2407 __ RecordPosition(RelocInfo::POSITION); |
2391 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), | 2408 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), |
2392 RelocInfo::CONSTRUCT_CALL); | 2409 RelocInfo::CONSTRUCT_CALL); |
2393 | 2410 |
2394 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). | 2411 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). |
2395 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | 2412 __ str(r0, frame_->Top()); |
2396 } | 2413 } |
2397 | 2414 |
2398 | 2415 |
2399 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 2416 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
2400 ASSERT(args->length() == 1); | 2417 ASSERT(args->length() == 1); |
2401 Label leave; | 2418 Label leave; |
2402 Load(args->at(0)); | 2419 Load(args->at(0)); |
2403 __ pop(r0); // r0 contains object. | 2420 __ pop(r0); // r0 contains object. |
2404 // if (object->IsSmi()) return the object. | 2421 // if (object->IsSmi()) return the object. |
2405 __ tst(r0, Operand(kSmiTagMask)); | 2422 __ tst(r0, Operand(kSmiTagMask)); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2558 // Push the builtins object found in the current global object. | 2575 // Push the builtins object found in the current global object. |
2559 __ ldr(r1, GlobalObject()); | 2576 __ ldr(r1, GlobalObject()); |
2560 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); | 2577 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); |
2561 __ push(r0); | 2578 __ push(r0); |
2562 | 2579 |
2563 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2580 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2564 | 2581 |
2565 // Call the JS runtime function. | 2582 // Call the JS runtime function. |
2566 Handle<Code> stub = ComputeCallInitialize(args->length()); | 2583 Handle<Code> stub = ComputeCallInitialize(args->length()); |
2567 __ Call(stub, RelocInfo::CODE_TARGET); | 2584 __ Call(stub, RelocInfo::CODE_TARGET); |
2568 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2585 __ ldr(cp, frame_->Context()); |
2569 __ pop(); | 2586 __ pop(); |
2570 __ push(r0); | 2587 __ push(r0); |
2571 } | 2588 } |
2572 } | 2589 } |
2573 | 2590 |
2574 | 2591 |
2575 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 2592 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
2576 Comment cmnt(masm_, "[ UnaryOperation"); | 2593 Comment cmnt(masm_, "[ UnaryOperation"); |
2577 | 2594 |
2578 Token::Value op = node->op(); | 2595 Token::Value op = node->op(); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2720 Label slow, exit; | 2737 Label slow, exit; |
2721 | 2738 |
2722 // Load the value (1) into register r1. | 2739 // Load the value (1) into register r1. |
2723 __ mov(r1, Operand(Smi::FromInt(1))); | 2740 __ mov(r1, Operand(Smi::FromInt(1))); |
2724 | 2741 |
2725 // Check for smi operand. | 2742 // Check for smi operand. |
2726 __ tst(r0, Operand(kSmiTagMask)); | 2743 __ tst(r0, Operand(kSmiTagMask)); |
2727 __ b(ne, &slow); | 2744 __ b(ne, &slow); |
2728 | 2745 |
2729 // Postfix: Store the old value as the result. | 2746 // Postfix: Store the old value as the result. |
2730 if (is_postfix) __ str(r0, MemOperand(sp, target.size() * kPointerSize)); | 2747 if (is_postfix) { |
2748 __ str(r0, frame_->Element(target.size())); | |
2749 } | |
2731 | 2750 |
2732 // Perform optimistic increment/decrement. | 2751 // Perform optimistic increment/decrement. |
2733 if (is_increment) { | 2752 if (is_increment) { |
2734 __ add(r0, r0, Operand(r1), SetCC); | 2753 __ add(r0, r0, Operand(r1), SetCC); |
2735 } else { | 2754 } else { |
2736 __ sub(r0, r0, Operand(r1), SetCC); | 2755 __ sub(r0, r0, Operand(r1), SetCC); |
2737 } | 2756 } |
2738 | 2757 |
2739 // If the increment/decrement didn't overflow, we're done. | 2758 // If the increment/decrement didn't overflow, we're done. |
2740 __ b(vc, &exit); | 2759 __ b(vc, &exit); |
2741 | 2760 |
2742 // Revert optimistic increment/decrement. | 2761 // Revert optimistic increment/decrement. |
2743 if (is_increment) { | 2762 if (is_increment) { |
2744 __ sub(r0, r0, Operand(r1)); | 2763 __ sub(r0, r0, Operand(r1)); |
2745 } else { | 2764 } else { |
2746 __ add(r0, r0, Operand(r1)); | 2765 __ add(r0, r0, Operand(r1)); |
2747 } | 2766 } |
2748 | 2767 |
2749 // Slow case: Convert to number. | 2768 // Slow case: Convert to number. |
2750 __ bind(&slow); | 2769 __ bind(&slow); |
2751 | 2770 |
2752 // Postfix: Convert the operand to a number and store it as the result. | 2771 // Postfix: Convert the operand to a number and store it as the result. |
2753 if (is_postfix) { | 2772 if (is_postfix) { |
2754 InvokeBuiltinStub stub(InvokeBuiltinStub::ToNumber, 2); | 2773 InvokeBuiltinStub stub(InvokeBuiltinStub::ToNumber, 2); |
2755 __ CallStub(&stub); | 2774 __ CallStub(&stub); |
2756 // Store to result (on the stack). | 2775 // Store to result (on the stack). |
2757 __ str(r0, MemOperand(sp, target.size() * kPointerSize)); | 2776 __ str(r0, frame_->Element(target.size())); |
2758 } | 2777 } |
2759 | 2778 |
2760 // Compute the new value by calling the right JavaScript native. | 2779 // Compute the new value by calling the right JavaScript native. |
2761 if (is_increment) { | 2780 if (is_increment) { |
2762 InvokeBuiltinStub stub(InvokeBuiltinStub::Inc, 1); | 2781 InvokeBuiltinStub stub(InvokeBuiltinStub::Inc, 1); |
2763 __ CallStub(&stub); | 2782 __ CallStub(&stub); |
2764 } else { | 2783 } else { |
2765 InvokeBuiltinStub stub(InvokeBuiltinStub::Dec, 1); | 2784 InvokeBuiltinStub stub(InvokeBuiltinStub::Dec, 1); |
2766 __ CallStub(&stub); | 2785 __ CallStub(&stub); |
2767 } | 2786 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2807 __ bind(&is_true); | 2826 __ bind(&is_true); |
2808 LoadCondition(node->right(), | 2827 LoadCondition(node->right(), |
2809 NOT_INSIDE_TYPEOF, | 2828 NOT_INSIDE_TYPEOF, |
2810 true_target(), | 2829 true_target(), |
2811 false_target(), | 2830 false_target(), |
2812 false); | 2831 false); |
2813 | 2832 |
2814 } else { | 2833 } else { |
2815 Label pop_and_continue, exit; | 2834 Label pop_and_continue, exit; |
2816 | 2835 |
2817 __ ldr(r0, MemOperand(sp, 0)); // dup the stack top | 2836 __ ldr(r0, frame_->Top()); // dup the stack top |
2818 __ push(r0); | 2837 __ push(r0); |
2819 // Avoid popping the result if it converts to 'false' using the | 2838 // Avoid popping the result if it converts to 'false' using the |
2820 // standard ToBoolean() conversion as described in ECMA-262, | 2839 // standard ToBoolean() conversion as described in ECMA-262, |
2821 // section 9.2, page 30. | 2840 // section 9.2, page 30. |
2822 ToBoolean(&pop_and_continue, &exit); | 2841 ToBoolean(&pop_and_continue, &exit); |
2823 Branch(false, &exit); | 2842 Branch(false, &exit); |
2824 | 2843 |
2825 // Pop the result of evaluating the first part. | 2844 // Pop the result of evaluating the first part. |
2826 __ bind(&pop_and_continue); | 2845 __ bind(&pop_and_continue); |
2827 __ pop(r0); | 2846 __ pop(r0); |
(...skipping 20 matching lines...) Expand all Loading... | |
2848 __ bind(&is_false); | 2867 __ bind(&is_false); |
2849 LoadCondition(node->right(), | 2868 LoadCondition(node->right(), |
2850 NOT_INSIDE_TYPEOF, | 2869 NOT_INSIDE_TYPEOF, |
2851 true_target(), | 2870 true_target(), |
2852 false_target(), | 2871 false_target(), |
2853 false); | 2872 false); |
2854 | 2873 |
2855 } else { | 2874 } else { |
2856 Label pop_and_continue, exit; | 2875 Label pop_and_continue, exit; |
2857 | 2876 |
2858 __ ldr(r0, MemOperand(sp, 0)); | 2877 __ ldr(r0, frame_->Top()); |
2859 __ push(r0); | 2878 __ push(r0); |
2860 // Avoid popping the result if it converts to 'true' using the | 2879 // Avoid popping the result if it converts to 'true' using the |
2861 // standard ToBoolean() conversion as described in ECMA-262, | 2880 // standard ToBoolean() conversion as described in ECMA-262, |
2862 // section 9.2, page 30. | 2881 // section 9.2, page 30. |
2863 ToBoolean(&exit, &pop_and_continue); | 2882 ToBoolean(&exit, &pop_and_continue); |
2864 Branch(true, &exit); | 2883 Branch(true, &exit); |
2865 | 2884 |
2866 // Pop the result of evaluating the first part. | 2885 // Pop the result of evaluating the first part. |
2867 __ bind(&pop_and_continue); | 2886 __ bind(&pop_and_continue); |
2868 __ pop(r0); | 2887 __ pop(r0); |
(...skipping 24 matching lines...) Expand all Loading... | |
2893 Load(node->left()); | 2912 Load(node->left()); |
2894 Load(node->right()); | 2913 Load(node->right()); |
2895 GenericBinaryOperation(node->op()); | 2914 GenericBinaryOperation(node->op()); |
2896 } | 2915 } |
2897 __ push(r0); | 2916 __ push(r0); |
2898 } | 2917 } |
2899 } | 2918 } |
2900 | 2919 |
2901 | 2920 |
2902 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 2921 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
2903 __ ldr(r0, FunctionOperand()); | 2922 __ ldr(r0, frame_->Function()); |
2904 __ push(r0); | 2923 __ push(r0); |
2905 } | 2924 } |
2906 | 2925 |
2907 | 2926 |
2908 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 2927 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
2909 Comment cmnt(masm_, "[ CompareOperation"); | 2928 Comment cmnt(masm_, "[ CompareOperation"); |
2910 | 2929 |
2911 // Get the expressions from the node. | 2930 // Get the expressions from the node. |
2912 Expression* left = node->left(); | 2931 Expression* left = node->left(); |
2913 Expression* right = node->right(); | 2932 Expression* right = node->right(); |
(...skipping 1315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4229 // Slow-case: Non-function called. | 4248 // Slow-case: Non-function called. |
4230 __ bind(&slow); | 4249 __ bind(&slow); |
4231 __ mov(r0, Operand(argc_)); // Setup the number of arguments. | 4250 __ mov(r0, Operand(argc_)); // Setup the number of arguments. |
4232 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS); | 4251 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS); |
4233 } | 4252 } |
4234 | 4253 |
4235 | 4254 |
4236 #undef __ | 4255 #undef __ |
4237 | 4256 |
4238 } } // namespace v8::internal | 4257 } } // namespace v8::internal |
OLD | NEW |