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

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

Issue 342035: Move the Location class into the AST Expression class as a member.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 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 | « no previous file | src/ast.h » ('j') | src/compiler.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/ast.h » ('j') | src/compiler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698