OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 __ RecordJSReturn(); | 110 __ RecordJSReturn(); |
111 __ mov(sp, fp); | 111 __ mov(sp, fp); |
112 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 112 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
113 int num_parameters = function_->scope()->num_parameters(); | 113 int num_parameters = function_->scope()->num_parameters(); |
114 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); | 114 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); |
115 __ Jump(lr); | 115 __ Jump(lr); |
116 } | 116 } |
117 } | 117 } |
118 | 118 |
119 | 119 |
120 void FastCodeGenerator::Move(Location destination, Slot* source) { | 120 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { |
121 switch (destination.type()) { | 121 switch (context) { |
122 case Location::kUninitialized: | 122 case Expression::kUninitialized: |
123 UNREACHABLE(); | 123 UNREACHABLE(); |
124 case Location::kEffect: | 124 case Expression::kEffect: |
125 break; | 125 break; |
126 case Location::kValue: | 126 case Expression::kValue: |
127 __ ldr(ip, MemOperand(fp, SlotOffset(source))); | 127 __ ldr(ip, MemOperand(fp, SlotOffset(source))); |
128 __ push(ip); | 128 __ push(ip); |
129 break; | 129 break; |
130 } | 130 } |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 void FastCodeGenerator::Move(Location destination, Literal* expr) { | 134 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { |
135 switch (destination.type()) { | 135 switch (context) { |
136 case Location::kUninitialized: | 136 case Expression::kUninitialized: |
137 UNREACHABLE(); | 137 UNREACHABLE(); |
138 case Location::kEffect: | 138 case Expression::kEffect: |
139 break; | 139 break; |
140 case Location::kValue: | 140 case Expression::kValue: |
141 __ mov(ip, Operand(expr->handle())); | 141 __ mov(ip, Operand(expr->handle())); |
142 __ push(ip); | 142 __ push(ip); |
143 break; | 143 break; |
144 } | 144 } |
145 } | 145 } |
146 | 146 |
147 | 147 |
148 void FastCodeGenerator::Move(Slot* destination, Location source) { | 148 void FastCodeGenerator::DropAndMove(Expression::Context context, |
149 switch (source.type()) { | 149 Register source) { |
150 case Location::kUninitialized: // Fall through. | 150 switch (context) { |
151 case Location::kEffect: | 151 case Expression::kUninitialized: |
152 UNREACHABLE(); | 152 UNREACHABLE(); |
153 case Location::kValue: | 153 case Expression::kEffect: |
154 __ pop(ip); | |
155 __ str(ip, MemOperand(fp, SlotOffset(destination))); | |
156 break; | |
157 } | |
158 } | |
159 | |
160 | |
161 void FastCodeGenerator::DropAndMove(Location destination, Register source) { | |
162 switch (destination.type()) { | |
163 case Location::kUninitialized: | |
164 UNREACHABLE(); | |
165 case Location::kEffect: | |
166 __ pop(); | 154 __ pop(); |
167 break; | 155 break; |
168 case Location::kValue: | 156 case Expression::kValue: |
169 __ str(source, MemOperand(sp)); | 157 __ str(source, MemOperand(sp)); |
170 break; | 158 break; |
171 } | 159 } |
172 } | 160 } |
173 | 161 |
174 | 162 |
175 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 163 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
176 // Call the runtime to declare the globals. | 164 // Call the runtime to declare the globals. |
177 // The context is the first argument. | 165 // The context is the first argument. |
178 __ mov(r1, Operand(pairs)); | 166 __ mov(r1, Operand(pairs)); |
179 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); | 167 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); |
180 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); | 168 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); |
181 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 169 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
182 // Return value is ignored. | 170 // Return value is ignored. |
183 } | 171 } |
184 | 172 |
185 | 173 |
186 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 174 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
187 Comment cmnt(masm_, "[ ReturnStatement"); | 175 Comment cmnt(masm_, "[ ReturnStatement"); |
188 SetStatementPosition(stmt); | 176 SetStatementPosition(stmt); |
189 Expression* expr = stmt->expression(); | 177 Expression* expr = stmt->expression(); |
190 // Complete the statement based on the type of the subexpression. | 178 // Complete the statement based on the type of the subexpression. |
191 if (expr->AsLiteral() != NULL) { | 179 ASSERT_EQ(Expression::kValue, expr->context()); |
William Hesse
2009/10/29 15:15:25
Why are you dropping the optimization for a consta
Kevin Millikin (Chromium)
2009/10/29 16:36:10
As part of getting rid of the move "location" -> r
| |
192 __ mov(r0, Operand(expr->AsLiteral()->handle())); | 180 Visit(expr); |
193 } else { | 181 __ pop(r0); |
194 Visit(expr); | |
195 Move(r0, expr->location()); | |
196 } | |
197 | 182 |
198 if (FLAG_trace) { | 183 if (FLAG_trace) { |
199 __ push(r0); | 184 __ push(r0); |
200 __ CallRuntime(Runtime::kTraceExit, 1); | 185 __ CallRuntime(Runtime::kTraceExit, 1); |
201 } | 186 } |
202 | 187 |
203 __ RecordJSReturn(); | 188 __ RecordJSReturn(); |
204 __ mov(sp, fp); | 189 __ mov(sp, fp); |
205 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 190 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
206 int num_parameters = function_->scope()->num_parameters(); | 191 int num_parameters = function_->scope()->num_parameters(); |
207 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); | 192 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); |
208 __ Jump(lr); | 193 __ Jump(lr); |
209 } | 194 } |
210 | 195 |
211 | 196 |
212 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 197 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
213 Comment cmnt(masm_, "[ FunctionLiteral"); | 198 Comment cmnt(masm_, "[ FunctionLiteral"); |
214 | 199 |
215 // Build the function boilerplate and instantiate it. | 200 // Build the function boilerplate and instantiate it. |
216 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); | 201 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); |
217 if (HasStackOverflow()) return; | 202 if (HasStackOverflow()) return; |
218 | 203 |
219 ASSERT(boilerplate->IsBoilerplate()); | 204 ASSERT(boilerplate->IsBoilerplate()); |
220 | 205 |
221 // Create a new closure. | 206 // Create a new closure. |
222 __ mov(r0, Operand(boilerplate)); | 207 __ mov(r0, Operand(boilerplate)); |
223 __ stm(db_w, sp, cp.bit() | r0.bit()); | 208 __ stm(db_w, sp, cp.bit() | r0.bit()); |
224 __ CallRuntime(Runtime::kNewClosure, 2); | 209 __ CallRuntime(Runtime::kNewClosure, 2); |
225 Move(expr->location(), r0); | 210 Move(expr->context(), r0); |
226 } | 211 } |
227 | 212 |
228 | 213 |
229 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 214 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
230 Comment cmnt(masm_, "[ VariableProxy"); | 215 Comment cmnt(masm_, "[ VariableProxy"); |
231 Expression* rewrite = expr->var()->rewrite(); | 216 Expression* rewrite = expr->var()->rewrite(); |
232 if (rewrite == NULL) { | 217 if (rewrite == NULL) { |
233 Comment cmnt(masm_, "Global variable"); | 218 Comment cmnt(masm_, "Global variable"); |
234 // Use inline caching. Variable name is passed in r2 and the global | 219 // Use inline caching. Variable name is passed in r2 and the global |
235 // object on the stack. | 220 // object on the stack. |
236 __ ldr(ip, CodeGenerator::GlobalObject()); | 221 __ ldr(ip, CodeGenerator::GlobalObject()); |
237 __ push(ip); | 222 __ push(ip); |
238 __ mov(r2, Operand(expr->name())); | 223 __ mov(r2, Operand(expr->name())); |
239 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 224 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
240 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 225 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
241 DropAndMove(expr->location(), r0); | 226 DropAndMove(expr->context(), r0); |
242 } else { | 227 } else { |
243 Comment cmnt(masm_, "Stack slot"); | 228 Comment cmnt(masm_, "Stack slot"); |
244 Move(expr->location(), rewrite->AsSlot()); | 229 Move(expr->context(), rewrite->AsSlot()); |
245 } | 230 } |
246 } | 231 } |
247 | 232 |
248 | 233 |
249 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 234 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
250 Comment cmnt(masm_, "[ RegExp Literal"); | 235 Comment cmnt(masm_, "[ RegExp Literal"); |
251 Label done; | 236 Label done; |
252 // Registers will be used as follows: | 237 // Registers will be used as follows: |
253 // r4 = JS function, literals array | 238 // r4 = JS function, literals array |
254 // r3 = literal index | 239 // r3 = literal index |
255 // r2 = RegExp pattern | 240 // r2 = RegExp pattern |
256 // r1 = RegExp flags | 241 // r1 = RegExp flags |
257 // r0 = temp + return value (RegExp literal) | 242 // r0 = temp + return value (RegExp literal) |
258 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 243 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
259 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 244 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
260 int literal_offset = | 245 int literal_offset = |
261 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 246 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
262 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | 247 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
263 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 248 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
264 __ cmp(r0, ip); | 249 __ cmp(r0, ip); |
265 __ b(ne, &done); | 250 __ b(ne, &done); |
266 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 251 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
267 __ mov(r2, Operand(expr->pattern())); | 252 __ mov(r2, Operand(expr->pattern())); |
268 __ mov(r1, Operand(expr->flags())); | 253 __ mov(r1, Operand(expr->flags())); |
269 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); | 254 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); |
270 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 255 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
271 __ bind(&done); | 256 __ bind(&done); |
272 Move(expr->location(), r0); | 257 Move(expr->context(), r0); |
273 } | 258 } |
274 | 259 |
275 | 260 |
276 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 261 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
277 Comment cmnt(masm_, "[ ObjectLiteral"); | 262 Comment cmnt(masm_, "[ ObjectLiteral"); |
278 Label boilerplate_exists; | 263 Label boilerplate_exists; |
279 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 264 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
280 // r2 = literal array (0). | 265 // r2 = literal array (0). |
281 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 266 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
282 int literal_offset = | 267 int literal_offset = |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
319 } | 304 } |
320 switch (property->kind()) { | 305 switch (property->kind()) { |
321 case ObjectLiteral::Property::CONSTANT: | 306 case ObjectLiteral::Property::CONSTANT: |
322 UNREACHABLE(); | 307 UNREACHABLE(); |
323 | 308 |
324 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // Fall through. | 309 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // Fall through. |
325 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 310 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
326 case ObjectLiteral::Property::COMPUTED: | 311 case ObjectLiteral::Property::COMPUTED: |
327 if (key->handle()->IsSymbol()) { | 312 if (key->handle()->IsSymbol()) { |
328 Visit(value); | 313 Visit(value); |
329 Move(r0, value->location()); | 314 ASSERT_EQ(Expression::kValue, value->context()); |
315 __ pop(r0); | |
330 __ mov(r2, Operand(key->handle())); | 316 __ mov(r2, Operand(key->handle())); |
331 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 317 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
332 __ Call(ic, RelocInfo::CODE_TARGET); | 318 __ Call(ic, RelocInfo::CODE_TARGET); |
333 // StoreIC leaves the receiver on the stack. | 319 // StoreIC leaves the receiver on the stack. |
334 break; | 320 break; |
335 } | 321 } |
336 // Fall through. | 322 // Fall through. |
337 | 323 |
338 case ObjectLiteral::Property::PROTOTYPE: | 324 case ObjectLiteral::Property::PROTOTYPE: |
339 __ push(r0); | 325 __ push(r0); |
340 Visit(key); | 326 Visit(key); |
341 ASSERT(key->location().is_value()); | 327 ASSERT_EQ(Expression::kValue, key->context()); |
342 Visit(value); | 328 Visit(value); |
343 ASSERT(value->location().is_value()); | 329 ASSERT_EQ(Expression::kValue, value->context()); |
344 __ CallRuntime(Runtime::kSetProperty, 3); | 330 __ CallRuntime(Runtime::kSetProperty, 3); |
345 __ ldr(r0, MemOperand(sp)); // Restore result into r0 | 331 __ ldr(r0, MemOperand(sp)); // Restore result into r0 |
346 break; | 332 break; |
347 | 333 |
348 case ObjectLiteral::Property::GETTER: // Fall through. | 334 case ObjectLiteral::Property::GETTER: // Fall through. |
349 case ObjectLiteral::Property::SETTER: | 335 case ObjectLiteral::Property::SETTER: |
350 __ push(r0); | 336 __ push(r0); |
351 Visit(key); | 337 Visit(key); |
352 ASSERT(key->location().is_value()); | 338 ASSERT_EQ(Expression::kValue, key->context()); |
353 __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? | 339 __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? |
354 Smi::FromInt(1) : | 340 Smi::FromInt(1) : |
355 Smi::FromInt(0))); | 341 Smi::FromInt(0))); |
356 __ push(r1); | 342 __ push(r1); |
357 Visit(value); | 343 Visit(value); |
358 ASSERT(value->location().is_value()); | 344 ASSERT_EQ(Expression::kValue, value->context()); |
359 __ CallRuntime(Runtime::kDefineAccessor, 4); | 345 __ CallRuntime(Runtime::kDefineAccessor, 4); |
360 __ ldr(r0, MemOperand(sp)); // Restore result into r0 | 346 __ ldr(r0, MemOperand(sp)); // Restore result into r0 |
361 break; | 347 break; |
362 } | 348 } |
363 } | 349 } |
364 switch (expr->location().type()) { | 350 switch (expr->context()) { |
365 case Location::kUninitialized: | 351 case Expression::kUninitialized: |
366 UNREACHABLE(); | 352 UNREACHABLE(); |
367 case Location::kEffect: | 353 case Expression::kEffect: |
368 if (result_saved) __ pop(); | 354 if (result_saved) __ pop(); |
369 break; | 355 break; |
370 case Location::kValue: | 356 case Expression::kValue: |
371 if (!result_saved) __ push(r0); | 357 if (!result_saved) __ push(r0); |
372 break; | 358 break; |
373 } | 359 } |
374 } | 360 } |
375 | 361 |
376 | 362 |
377 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 363 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
378 Comment cmnt(masm_, "[ ArrayLiteral"); | 364 Comment cmnt(masm_, "[ ArrayLiteral"); |
379 Label make_clone; | 365 Label make_clone; |
380 | 366 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 if (subexpr->AsLiteral() != NULL || | 402 if (subexpr->AsLiteral() != NULL || |
417 CompileTimeValue::IsCompileTimeValue(subexpr)) { | 403 CompileTimeValue::IsCompileTimeValue(subexpr)) { |
418 continue; | 404 continue; |
419 } | 405 } |
420 | 406 |
421 if (!result_saved) { | 407 if (!result_saved) { |
422 __ push(r0); | 408 __ push(r0); |
423 result_saved = true; | 409 result_saved = true; |
424 } | 410 } |
425 Visit(subexpr); | 411 Visit(subexpr); |
426 ASSERT(subexpr->location().is_value()); | 412 ASSERT_EQ(Expression::kValue, subexpr->context()); |
427 | 413 |
428 // Store the subexpression value in the array's elements. | 414 // Store the subexpression value in the array's elements. |
429 __ pop(r0); // Subexpression value. | 415 __ pop(r0); // Subexpression value. |
430 __ ldr(r1, MemOperand(sp)); // Copy of array literal. | 416 __ ldr(r1, MemOperand(sp)); // Copy of array literal. |
431 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 417 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
432 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 418 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
433 __ str(r0, FieldMemOperand(r1, offset)); | 419 __ str(r0, FieldMemOperand(r1, offset)); |
434 | 420 |
435 // Update the write barrier for the array store with r0 as the scratch | 421 // Update the write barrier for the array store with r0 as the scratch |
436 // register. | 422 // register. |
437 __ mov(r2, Operand(offset)); | 423 __ mov(r2, Operand(offset)); |
438 __ RecordWrite(r1, r2, r0); | 424 __ RecordWrite(r1, r2, r0); |
439 } | 425 } |
440 | 426 |
441 switch (expr->location().type()) { | 427 switch (expr->context()) { |
442 case Location::kUninitialized: | 428 case Expression::kUninitialized: |
443 UNREACHABLE(); | 429 UNREACHABLE(); |
444 case Location::kEffect: | 430 case Expression::kEffect: |
445 if (result_saved) __ pop(); | 431 if (result_saved) __ pop(); |
446 break; | 432 break; |
447 case Location::kValue: | 433 case Expression::kValue: |
448 if (!result_saved) __ push(r0); | 434 if (!result_saved) __ push(r0); |
449 break; | 435 break; |
450 } | 436 } |
451 } | 437 } |
452 | 438 |
453 | 439 |
454 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 440 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
455 Comment cmnt(masm_, "[ Assignment"); | 441 Comment cmnt(masm_, "[ Assignment"); |
456 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 442 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
457 | 443 |
458 // Left-hand side can only be a global or a (parameter or local) slot. | 444 // Left-hand side can only be a global or a (parameter or local) slot. |
459 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 445 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
460 ASSERT(var != NULL); | 446 ASSERT(var != NULL); |
461 ASSERT(var->is_global() || var->slot() != NULL); | 447 ASSERT(var->is_global() || var->slot() != NULL); |
462 | 448 |
463 Expression* rhs = expr->value(); | 449 Expression* rhs = expr->value(); |
464 Location destination = expr->location(); | |
465 if (var->is_global()) { | 450 if (var->is_global()) { |
466 // Assignment to a global variable, use inline caching. Right-hand-side | 451 // Assignment to a global variable, use inline caching. Right-hand-side |
467 // value is passed in r0, variable name in r2, and the global object on | 452 // value is passed in r0, variable name in r2, and the global object on |
468 // the stack. | 453 // the stack. |
469 | 454 |
470 // Code for the right-hand-side expression depends on its type. | 455 // Code for the right-hand-side expression depends on its type. |
471 if (rhs->AsLiteral() != NULL) { | 456 if (rhs->AsLiteral() != NULL) { |
472 __ mov(r0, Operand(rhs->AsLiteral()->handle())); | 457 __ mov(r0, Operand(rhs->AsLiteral()->handle())); |
473 } else { | 458 } else { |
474 ASSERT(rhs->location().is_value()); | 459 ASSERT_EQ(Expression::kValue, rhs->context()); |
475 Visit(rhs); | 460 Visit(rhs); |
476 __ pop(r0); | 461 __ pop(r0); |
477 } | 462 } |
478 __ mov(r2, Operand(var->name())); | 463 __ mov(r2, Operand(var->name())); |
479 __ ldr(ip, CodeGenerator::GlobalObject()); | 464 __ ldr(ip, CodeGenerator::GlobalObject()); |
480 __ push(ip); | 465 __ push(ip); |
481 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 466 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
482 __ Call(ic, RelocInfo::CODE_TARGET); | 467 __ Call(ic, RelocInfo::CODE_TARGET); |
483 // Overwrite the global object on the stack with the result if needed. | 468 // Overwrite the global object on the stack with the result if needed. |
484 DropAndMove(expr->location(), r0); | 469 DropAndMove(expr->context(), r0); |
485 } else { | 470 } else { |
486 // Local or parameter assignment. | 471 // Local or parameter assignment. |
487 | 472 |
488 // Code for the right-hand side expression depends on its type. | 473 // Code for the right-hand side expression depends on its type. |
489 if (rhs->AsLiteral() != NULL) { | 474 if (rhs->AsLiteral() != NULL) { |
490 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 475 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a |
491 // discarded result. Always perform the assignment. | 476 // discarded result. Always perform the assignment. |
492 __ mov(ip, Operand(rhs->AsLiteral()->handle())); | 477 __ mov(ip, Operand(rhs->AsLiteral()->handle())); |
493 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); | 478 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
494 Move(expr->location(), ip); | 479 Move(expr->context(), ip); |
495 } else { | 480 } else { |
496 ASSERT(rhs->location().is_value()); | 481 ASSERT_EQ(Expression::kValue, rhs->context()); |
497 Visit(rhs); | 482 Visit(rhs); |
498 // Load right-hand side into ip. | 483 // Load right-hand side into ip. |
499 switch (expr->location().type()) { | 484 switch (expr->context()) { |
500 case Location::kUninitialized: | 485 case Expression::kUninitialized: |
501 UNREACHABLE(); | 486 UNREACHABLE(); |
502 case Location::kEffect: | 487 case Expression::kEffect: |
503 // Case 'var = temp'. Discard right-hand-side temporary. | 488 // Case 'var = temp'. Discard right-hand-side temporary. |
504 __ pop(ip); | 489 __ pop(ip); |
505 break; | 490 break; |
506 case Location::kValue: | 491 case Expression::kValue: |
507 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side | 492 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side |
508 // temporary on the stack. | 493 // temporary on the stack. |
509 __ ldr(ip, MemOperand(sp)); | 494 __ ldr(ip, MemOperand(sp)); |
510 break; | 495 break; |
511 } | 496 } |
512 // Do the slot assignment. | 497 // Do the slot assignment. |
513 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); | 498 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
514 } | 499 } |
515 } | 500 } |
516 } | 501 } |
(...skipping 24 matching lines...) Expand all Loading... | |
541 // Do a KEYED property load. | 526 // Do a KEYED property load. |
542 Visit(expr->key()); | 527 Visit(expr->key()); |
543 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 528 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
544 __ Call(ic, RelocInfo::CODE_TARGET); | 529 __ Call(ic, RelocInfo::CODE_TARGET); |
545 // By emitting a nop we make sure that we do not have a "test eax,..." | 530 // By emitting a nop we make sure that we do not have a "test eax,..." |
546 // instruction after the call it is treated specially by the LoadIC code. | 531 // instruction after the call it is treated specially by the LoadIC code. |
547 __ nop(); | 532 __ nop(); |
548 // Drop key and receiver left on the stack by IC. | 533 // Drop key and receiver left on the stack by IC. |
549 __ pop(); | 534 __ pop(); |
550 } | 535 } |
551 switch (expr->location().type()) { | 536 DropAndMove(expr->context(), r0); |
552 case Location::kUninitialized: | |
553 UNREACHABLE(); | |
554 case Location::kValue: | |
555 __ str(r0, MemOperand(sp)); | |
556 break; | |
557 case Location::kEffect: | |
558 __ pop(); | |
559 } | |
560 } | 537 } |
561 | 538 |
562 | 539 |
563 void FastCodeGenerator::VisitCall(Call* expr) { | 540 void FastCodeGenerator::VisitCall(Call* expr) { |
564 Comment cmnt(masm_, "[ Call"); | 541 Comment cmnt(masm_, "[ Call"); |
565 Expression* fun = expr->expression(); | 542 Expression* fun = expr->expression(); |
566 ZoneList<Expression*>* args = expr->arguments(); | 543 ZoneList<Expression*>* args = expr->arguments(); |
567 Variable* var = fun->AsVariableProxy()->AsVariable(); | 544 Variable* var = fun->AsVariableProxy()->AsVariable(); |
568 ASSERT(var != NULL && !var->is_this() && var->is_global()); | 545 ASSERT(var != NULL && !var->is_this() && var->is_global()); |
569 ASSERT(!var->is_possibly_eval()); | 546 ASSERT(!var->is_possibly_eval()); |
570 | 547 |
571 __ mov(r1, Operand(var->name())); | 548 __ mov(r1, Operand(var->name())); |
572 // Push global object as receiver. | 549 // Push global object as receiver. |
573 __ ldr(r0, CodeGenerator::GlobalObject()); | 550 __ ldr(r0, CodeGenerator::GlobalObject()); |
574 __ stm(db_w, sp, r1.bit() | r0.bit()); | 551 __ stm(db_w, sp, r1.bit() | r0.bit()); |
575 int arg_count = args->length(); | 552 int arg_count = args->length(); |
576 for (int i = 0; i < arg_count; i++) { | 553 for (int i = 0; i < arg_count; i++) { |
577 Visit(args->at(i)); | 554 Visit(args->at(i)); |
578 ASSERT(args->at(i)->location().is_value()); | 555 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
579 } | 556 } |
580 // Record source position for debugger | 557 // Record source position for debugger |
581 SetSourcePosition(expr->position()); | 558 SetSourcePosition(expr->position()); |
582 // Call the IC initialization code. | 559 // Call the IC initialization code. |
583 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 560 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
584 NOT_IN_LOOP); | 561 NOT_IN_LOOP); |
585 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 562 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
586 // Restore context register. | 563 // Restore context register. |
587 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 564 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
588 DropAndMove(expr->location(), r0); | 565 DropAndMove(expr->context(), r0); |
589 } | 566 } |
590 | 567 |
591 | 568 |
592 void FastCodeGenerator::VisitCallNew(CallNew* node) { | 569 void FastCodeGenerator::VisitCallNew(CallNew* expr) { |
593 Comment cmnt(masm_, "[ CallNew"); | 570 Comment cmnt(masm_, "[ CallNew"); |
594 // According to ECMA-262, section 11.2.2, page 44, the function | 571 // According to ECMA-262, section 11.2.2, page 44, the function |
595 // expression in new calls must be evaluated before the | 572 // expression in new calls must be evaluated before the |
596 // arguments. | 573 // arguments. |
597 // Push function on the stack. | 574 // Push function on the stack. |
598 Visit(node->expression()); | 575 Visit(expr->expression()); |
599 ASSERT(node->expression()->location().is_value()); | 576 ASSERT_EQ(Expression::kValue, expr->expression()->context()); |
600 | 577 |
601 // Push global object (receiver). | 578 // Push global object (receiver). |
602 __ ldr(r0, CodeGenerator::GlobalObject()); | 579 __ ldr(r0, CodeGenerator::GlobalObject()); |
603 __ push(r0); | 580 __ push(r0); |
604 // Push the arguments ("left-to-right") on the stack. | 581 // Push the arguments ("left-to-right") on the stack. |
605 ZoneList<Expression*>* args = node->arguments(); | 582 ZoneList<Expression*>* args = expr->arguments(); |
606 int arg_count = args->length(); | 583 int arg_count = args->length(); |
607 for (int i = 0; i < arg_count; i++) { | 584 for (int i = 0; i < arg_count; i++) { |
608 Visit(args->at(i)); | 585 Visit(args->at(i)); |
609 ASSERT(args->at(i)->location().is_value()); | 586 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
610 // If location is value, it is already on the stack, | 587 // If location is value, it is already on the stack, |
611 // so nothing to do here. | 588 // so nothing to do here. |
612 } | 589 } |
613 | 590 |
614 // Call the construct call builtin that handles allocation and | 591 // Call the construct call builtin that handles allocation and |
615 // constructor invocation. | 592 // constructor invocation. |
616 SetSourcePosition(node->position()); | 593 SetSourcePosition(expr->position()); |
617 | 594 |
618 // Load function, arg_count into r1 and r0. | 595 // Load function, arg_count into r1 and r0. |
619 __ mov(r0, Operand(arg_count)); | 596 __ mov(r0, Operand(arg_count)); |
620 // Function is in esp[arg_count + 1]. | 597 // Function is in esp[arg_count + 1]. |
621 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 598 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
622 | 599 |
623 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 600 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
624 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 601 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
625 | 602 |
626 // Replace function on TOS with result in r0, or pop it. | 603 // Replace function on TOS with result in r0, or pop it. |
627 DropAndMove(node->location(), r0); | 604 DropAndMove(expr->context(), r0); |
628 } | 605 } |
629 | 606 |
630 | 607 |
631 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 608 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
632 Comment cmnt(masm_, "[ CallRuntime"); | 609 Comment cmnt(masm_, "[ CallRuntime"); |
633 ZoneList<Expression*>* args = expr->arguments(); | 610 ZoneList<Expression*>* args = expr->arguments(); |
634 Runtime::Function* function = expr->function(); | 611 Runtime::Function* function = expr->function(); |
635 | 612 |
636 ASSERT(function != NULL); | 613 ASSERT(function != NULL); |
637 | 614 |
638 // Push the arguments ("left-to-right"). | 615 // Push the arguments ("left-to-right"). |
639 int arg_count = args->length(); | 616 int arg_count = args->length(); |
640 for (int i = 0; i < arg_count; i++) { | 617 for (int i = 0; i < arg_count; i++) { |
641 Visit(args->at(i)); | 618 Visit(args->at(i)); |
642 ASSERT(args->at(i)->location().is_value()); | 619 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
643 } | 620 } |
644 | 621 |
645 __ CallRuntime(function, arg_count); | 622 __ CallRuntime(function, arg_count); |
646 Move(expr->location(), r0); | 623 Move(expr->context(), r0); |
647 } | 624 } |
648 | 625 |
649 | 626 |
650 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 627 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
651 switch (expr->op()) { | 628 switch (expr->op()) { |
652 case Token::COMMA: | 629 case Token::COMMA: |
653 ASSERT(expr->left()->location().is_effect()); | 630 ASSERT_EQ(Expression::kEffect, expr->left()->context()); |
654 ASSERT_EQ(expr->right()->location().type(), expr->location().type()); | 631 ASSERT_EQ(expr->context(), expr->right()->context()); |
655 Visit(expr->left()); | 632 Visit(expr->left()); |
656 Visit(expr->right()); | 633 Visit(expr->right()); |
657 break; | 634 break; |
658 | 635 |
659 case Token::OR: | 636 case Token::OR: |
660 case Token::AND: | 637 case Token::AND: |
661 EmitLogicalOperation(expr); | 638 EmitLogicalOperation(expr); |
662 break; | 639 break; |
663 | 640 |
664 case Token::ADD: | 641 case Token::ADD: |
665 case Token::SUB: | 642 case Token::SUB: |
666 case Token::DIV: | 643 case Token::DIV: |
667 case Token::MOD: | 644 case Token::MOD: |
668 case Token::MUL: | 645 case Token::MUL: |
669 case Token::BIT_OR: | 646 case Token::BIT_OR: |
670 case Token::BIT_AND: | 647 case Token::BIT_AND: |
671 case Token::BIT_XOR: | 648 case Token::BIT_XOR: |
672 case Token::SHL: | 649 case Token::SHL: |
673 case Token::SHR: | 650 case Token::SHR: |
674 case Token::SAR: { | 651 case Token::SAR: { |
675 ASSERT(expr->left()->location().is_value()); | 652 ASSERT_EQ(Expression::kValue, expr->left()->context()); |
676 ASSERT(expr->right()->location().is_value()); | 653 ASSERT_EQ(Expression::kValue, expr->right()->context()); |
677 | 654 |
678 Visit(expr->left()); | 655 Visit(expr->left()); |
679 Visit(expr->right()); | 656 Visit(expr->right()); |
680 __ pop(r0); | 657 __ pop(r0); |
681 __ pop(r1); | 658 __ pop(r1); |
682 GenericBinaryOpStub stub(expr->op(), | 659 GenericBinaryOpStub stub(expr->op(), |
683 NO_OVERWRITE); | 660 NO_OVERWRITE); |
684 __ CallStub(&stub); | 661 __ CallStub(&stub); |
685 Move(expr->location(), r0); | 662 Move(expr->context(), r0); |
686 | 663 |
687 break; | 664 break; |
688 } | 665 } |
689 default: | 666 default: |
690 UNREACHABLE(); | 667 UNREACHABLE(); |
691 } | 668 } |
692 } | 669 } |
693 | 670 |
694 | 671 |
695 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { | 672 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
696 // Compile a short-circuited boolean operation in a non-test context. | 673 // Compile a short-circuited boolean operation in a non-test context. |
697 | 674 |
698 // Compile (e0 || e1) as if it were | 675 // Compile (e0 || e1) as if it were |
699 // (let (temp = e0) temp ? temp : e1). | 676 // (let (temp = e0) temp ? temp : e1). |
700 // Compile (e0 && e1) as if it were | 677 // Compile (e0 && e1) as if it were |
701 // (let (temp = e0) !temp ? temp : e1). | 678 // (let (temp = e0) !temp ? temp : e1). |
702 | 679 |
703 Label done; | 680 Label done; |
704 Location destination = expr->location(); | 681 Expression::Context context = expr->context(); |
705 Expression* left = expr->left(); | 682 Expression* left = expr->left(); |
706 Expression* right = expr->right(); | 683 Expression* right = expr->right(); |
707 | 684 |
708 // Call the runtime to find the boolean value of the left-hand | 685 // Call the runtime to find the boolean value of the left-hand |
709 // subexpression. Duplicate the value if it may be needed as the final | 686 // subexpression. Duplicate the value if it may be needed as the final |
710 // result. | 687 // result. |
711 if (left->AsLiteral() != NULL) { | 688 if (left->AsLiteral() != NULL) { |
712 __ mov(r0, Operand(left->AsLiteral()->handle())); | 689 __ mov(r0, Operand(left->AsLiteral()->handle())); |
713 __ push(r0); | 690 __ push(r0); |
714 if (destination.is_value()) __ push(r0); | 691 if (context == Expression::kValue) __ push(r0); |
715 } else { | 692 } else { |
716 Visit(left); | 693 Visit(left); |
717 ASSERT(left->location().is_value()); | 694 ASSERT_EQ(Expression::kValue, left->context()); |
718 if (destination.is_value()) { | 695 if (context == Expression::kValue) { |
719 __ ldr(r0, MemOperand(sp)); | 696 __ ldr(r0, MemOperand(sp)); |
720 __ push(r0); | 697 __ push(r0); |
721 } | 698 } |
722 } | 699 } |
723 // The left-hand value is in on top of the stack. It is duplicated on the | 700 // The left-hand value is in on top of the stack. It is duplicated on the |
724 // stack iff the destination location is value. | 701 // stack iff the destination location is value. |
725 __ CallRuntime(Runtime::kToBool, 1); | 702 __ CallRuntime(Runtime::kToBool, 1); |
726 if (expr->op() == Token::OR) { | 703 if (expr->op() == Token::OR) { |
727 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 704 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
728 } else { | 705 } else { |
729 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 706 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
730 } | 707 } |
731 __ cmp(r0, ip); | 708 __ cmp(r0, ip); |
732 __ b(eq, &done); | 709 __ b(eq, &done); |
733 | 710 |
734 // Discard the left-hand value if present on the stack. | 711 // Discard the left-hand value if present on the stack. |
735 if (destination.is_value()) __ pop(); | 712 if (context == Expression::kValue) __ pop(); |
736 // Save or discard the right-hand value as needed. | 713 // Save or discard the right-hand value as needed. |
737 Visit(right); | 714 Visit(right); |
738 ASSERT_EQ(destination.type(), right->location().type()); | 715 ASSERT_EQ(context, right->context()); |
739 | 716 |
740 __ bind(&done); | 717 __ bind(&done); |
741 } | 718 } |
742 | 719 |
743 } } // namespace v8::internal | 720 } } // namespace v8::internal |
OLD | NEW |