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

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

Powered by Google App Engine
This is Rietveld 408576698