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

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

Issue 7302: Initial port of VirtualFrame to the ARM architecture. To reduce the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « src/codegen-arm.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/codegen-arm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698