| 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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 } | 195 } |
| 196 // Check that the size of the code used for returning matches what is | 196 // Check that the size of the code used for returning matches what is |
| 197 // expected by the debugger. | 197 // expected by the debugger. |
| 198 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 198 ASSERT_EQ(Assembler::kJSReturnSequenceLength, |
| 199 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 199 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
| 200 #endif | 200 #endif |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 | 203 |
| 204 | 204 |
| 205 void FastCodeGenerator::Move(Expression::Context context, Register source) { | 205 void FastCodeGenerator::Apply(Expression::Context context, |
| 206 Slot* slot, |
| 207 Register scratch) { |
| 208 switch (context) { |
| 209 case Expression::kUninitialized: |
| 210 UNREACHABLE(); |
| 211 case Expression::kEffect: |
| 212 break; |
| 213 case Expression::kValue: { |
| 214 MemOperand location = EmitSlotSearch(slot, scratch); |
| 215 __ push(location); |
| 216 break; |
| 217 } |
| 218 case Expression::kTest: |
| 219 case Expression::kValueTest: |
| 220 case Expression::kTestValue: |
| 221 Move(scratch, slot); |
| 222 Apply(context, scratch); |
| 223 break; |
| 224 } |
| 225 } |
| 226 |
| 227 |
| 228 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
| 206 switch (context) { | 229 switch (context) { |
| 207 case Expression::kUninitialized: | 230 case Expression::kUninitialized: |
| 208 UNREACHABLE(); | 231 UNREACHABLE(); |
| 209 case Expression::kEffect: | 232 case Expression::kEffect: |
| 210 break; | 233 break; |
| 211 case Expression::kValue: | 234 case Expression::kValue: |
| 212 __ push(source); | 235 __ Push(lit->handle()); |
| 213 break; | 236 break; |
| 214 case Expression::kTest: | 237 case Expression::kTest: |
| 215 TestAndBranch(source, true_label_, false_label_); | 238 case Expression::kValueTest: |
| 239 case Expression::kTestValue: |
| 240 __ Move(rax, lit->handle()); |
| 241 Apply(context, rax); |
| 216 break; | 242 break; |
| 217 case Expression::kValueTest: { | |
| 218 Label discard; | |
| 219 __ push(source); | |
| 220 TestAndBranch(source, true_label_, &discard); | |
| 221 __ bind(&discard); | |
| 222 __ addq(rsp, Immediate(kPointerSize)); | |
| 223 __ jmp(false_label_); | |
| 224 break; | |
| 225 } | |
| 226 case Expression::kTestValue: { | |
| 227 Label discard; | |
| 228 __ push(source); | |
| 229 TestAndBranch(source, &discard, false_label_); | |
| 230 __ bind(&discard); | |
| 231 __ addq(rsp, Immediate(kPointerSize)); | |
| 232 __ jmp(true_label_); | |
| 233 break; | |
| 234 } | |
| 235 } | 243 } |
| 236 } | 244 } |
| 237 | 245 |
| 238 | 246 |
| 239 void FastCodeGenerator::MoveTOS(Expression::Context context) { | 247 void FastCodeGenerator::ApplyTOS(Expression::Context context) { |
| 240 switch (context) { | 248 switch (context) { |
| 241 case Expression::kUninitialized: | 249 case Expression::kUninitialized: |
| 242 UNREACHABLE(); | 250 UNREACHABLE(); |
| 243 case Expression::kEffect: | 251 case Expression::kEffect: |
| 244 __ Drop(1); | 252 __ Drop(1); |
| 245 break; | 253 break; |
| 246 case Expression::kValue: | 254 case Expression::kValue: |
| 247 break; | 255 break; |
| 248 case Expression::kTest: | 256 case Expression::kTest: |
| 249 __ pop(rax); | 257 __ pop(rax); |
| 250 TestAndBranch(rax, true_label_, false_label_); | 258 TestAndBranch(rax, true_label_, false_label_); |
| 251 break; | 259 break; |
| 252 case Expression::kValueTest: { | 260 case Expression::kValueTest: { |
| 253 Label discard; | 261 Label discard; |
| 254 __ movq(rax, Operand(rsp, 0)); | 262 __ movq(rax, Operand(rsp, 0)); |
| 255 TestAndBranch(rax, true_label_, &discard); | 263 TestAndBranch(rax, true_label_, &discard); |
| 256 __ bind(&discard); | 264 __ bind(&discard); |
| 257 __ Drop(1); | 265 __ Drop(1); |
| 258 __ jmp(false_label_); | 266 __ jmp(false_label_); |
| 267 break; |
| 268 } |
| 269 case Expression::kTestValue: { |
| 270 Label discard; |
| 271 __ movq(rax, Operand(rsp, 0)); |
| 272 TestAndBranch(rax, &discard, false_label_); |
| 273 __ bind(&discard); |
| 274 __ Drop(1); |
| 275 __ jmp(true_label_); |
| 276 } |
| 277 } |
| 278 } |
| 279 |
| 280 |
| 281 void FastCodeGenerator::DropAndApply(int count, |
| 282 Expression::Context context, |
| 283 Register reg) { |
| 284 ASSERT(count > 0); |
| 285 ASSERT(!reg.is(rsp)); |
| 286 switch (context) { |
| 287 case Expression::kUninitialized: |
| 288 UNREACHABLE(); |
| 289 case Expression::kEffect: |
| 290 __ Drop(count); |
| 291 break; |
| 292 case Expression::kValue: |
| 293 if (count > 1) __ Drop(count - 1); |
| 294 __ movq(Operand(rsp, 0), reg); |
| 295 break; |
| 296 case Expression::kTest: |
| 297 __ Drop(count); |
| 298 TestAndBranch(reg, true_label_, false_label_); |
| 299 break; |
| 300 case Expression::kValueTest: { |
| 301 Label discard; |
| 302 if (count > 1) __ Drop(count - 1); |
| 303 __ movq(Operand(rsp, 0), reg); |
| 304 TestAndBranch(reg, true_label_, &discard); |
| 305 __ bind(&discard); |
| 306 __ Drop(1); |
| 307 __ jmp(false_label_); |
| 259 break; | 308 break; |
| 260 } | 309 } |
| 261 case Expression::kTestValue: { | 310 case Expression::kTestValue: { |
| 262 Label discard; | 311 Label discard; |
| 263 __ movq(rax, Operand(rsp, 0)); | 312 if (count > 1) __ Drop(count - 1); |
| 264 TestAndBranch(rax, &discard, false_label_); | 313 __ movq(Operand(rsp, 0), reg); |
| 314 TestAndBranch(reg, &discard, false_label_); |
| 265 __ bind(&discard); | 315 __ bind(&discard); |
| 266 __ Drop(1); | 316 __ Drop(1); |
| 267 __ jmp(true_label_); | 317 __ jmp(true_label_); |
| 318 break; |
| 268 } | 319 } |
| 269 } | 320 } |
| 270 } | 321 } |
| 271 | 322 |
| 272 | 323 |
| 273 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 324 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
| 274 switch (slot->type()) { | 325 switch (slot->type()) { |
| 275 case Slot::PARAMETER: | 326 case Slot::PARAMETER: |
| 276 case Slot::LOCAL: | 327 case Slot::LOCAL: |
| 277 return Operand(rbp, SlotOffset(slot)); | 328 return Operand(rbp, SlotOffset(slot)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 288 return Operand(rax, 0); | 339 return Operand(rax, 0); |
| 289 } | 340 } |
| 290 | 341 |
| 291 | 342 |
| 292 void FastCodeGenerator::Move(Register destination, Slot* source) { | 343 void FastCodeGenerator::Move(Register destination, Slot* source) { |
| 293 MemOperand location = EmitSlotSearch(source, destination); | 344 MemOperand location = EmitSlotSearch(source, destination); |
| 294 __ movq(destination, location); | 345 __ movq(destination, location); |
| 295 } | 346 } |
| 296 | 347 |
| 297 | 348 |
| 298 void FastCodeGenerator::Move(Expression::Context context, | |
| 299 Slot* source, | |
| 300 Register scratch) { | |
| 301 switch (context) { | |
| 302 case Expression::kUninitialized: | |
| 303 UNREACHABLE(); | |
| 304 case Expression::kEffect: | |
| 305 break; | |
| 306 case Expression::kValue: { | |
| 307 MemOperand location = EmitSlotSearch(source, scratch); | |
| 308 __ push(location); | |
| 309 break; | |
| 310 } | |
| 311 case Expression::kTest: | |
| 312 case Expression::kValueTest: | |
| 313 case Expression::kTestValue: | |
| 314 Move(scratch, source); | |
| 315 Move(context, scratch); | |
| 316 break; | |
| 317 } | |
| 318 } | |
| 319 | |
| 320 | |
| 321 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { | |
| 322 switch (context) { | |
| 323 case Expression::kUninitialized: | |
| 324 UNREACHABLE(); | |
| 325 case Expression::kEffect: | |
| 326 break; | |
| 327 case Expression::kValue: | |
| 328 __ Push(expr->handle()); | |
| 329 break; | |
| 330 case Expression::kTest: | |
| 331 case Expression::kValueTest: | |
| 332 case Expression::kTestValue: | |
| 333 __ Move(rax, expr->handle()); | |
| 334 Move(context, rax); | |
| 335 break; | |
| 336 } | |
| 337 } | |
| 338 | |
| 339 | |
| 340 void FastCodeGenerator::Move(Slot* dst, | 349 void FastCodeGenerator::Move(Slot* dst, |
| 341 Register src, | 350 Register src, |
| 342 Register scratch1, | 351 Register scratch1, |
| 343 Register scratch2) { | 352 Register scratch2) { |
| 344 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 353 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 345 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 354 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 346 MemOperand location = EmitSlotSearch(dst, scratch1); | 355 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 347 __ movq(location, src); | 356 __ movq(location, src); |
| 348 // Emit the write barrier code if the location is in the heap. | 357 // Emit the write barrier code if the location is in the heap. |
| 349 if (dst->type() == Slot::CONTEXT) { | 358 if (dst->type() == Slot::CONTEXT) { |
| 350 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | 359 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
| 351 __ RecordWrite(scratch1, offset, src, scratch2); | 360 __ RecordWrite(scratch1, offset, src, scratch2); |
| 352 } | 361 } |
| 353 } | 362 } |
| 354 | 363 |
| 355 | 364 |
| 356 void FastCodeGenerator::DropAndMove(Expression::Context context, | |
| 357 Register source, | |
| 358 int drop_count) { | |
| 359 ASSERT(drop_count > 0); | |
| 360 switch (context) { | |
| 361 case Expression::kUninitialized: | |
| 362 UNREACHABLE(); | |
| 363 case Expression::kEffect: | |
| 364 __ addq(rsp, Immediate(drop_count * kPointerSize)); | |
| 365 break; | |
| 366 case Expression::kValue: | |
| 367 if (drop_count > 1) { | |
| 368 __ addq(rsp, Immediate((drop_count - 1) * kPointerSize)); | |
| 369 } | |
| 370 __ movq(Operand(rsp, 0), source); | |
| 371 break; | |
| 372 case Expression::kTest: | |
| 373 ASSERT(!source.is(rsp)); | |
| 374 __ addq(rsp, Immediate(drop_count * kPointerSize)); | |
| 375 TestAndBranch(source, true_label_, false_label_); | |
| 376 break; | |
| 377 case Expression::kValueTest: { | |
| 378 Label discard; | |
| 379 if (drop_count > 1) { | |
| 380 __ addq(rsp, Immediate((drop_count - 1) * kPointerSize)); | |
| 381 } | |
| 382 __ movq(Operand(rsp, 0), source); | |
| 383 TestAndBranch(source, true_label_, &discard); | |
| 384 __ bind(&discard); | |
| 385 __ addq(rsp, Immediate(kPointerSize)); | |
| 386 __ jmp(false_label_); | |
| 387 break; | |
| 388 } | |
| 389 case Expression::kTestValue: { | |
| 390 Label discard; | |
| 391 __ movq(Operand(rsp, 0), source); | |
| 392 TestAndBranch(source, &discard, false_label_); | |
| 393 __ bind(&discard); | |
| 394 __ addq(rsp, Immediate(kPointerSize)); | |
| 395 __ jmp(true_label_); | |
| 396 break; | |
| 397 } | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 | |
| 402 void FastCodeGenerator::TestAndBranch(Register source, | 365 void FastCodeGenerator::TestAndBranch(Register source, |
| 403 Label* true_label, | 366 Label* true_label, |
| 404 Label* false_label) { | 367 Label* false_label) { |
| 405 ASSERT_NE(NULL, true_label); | 368 ASSERT_NE(NULL, true_label); |
| 406 ASSERT_NE(NULL, false_label); | 369 ASSERT_NE(NULL, false_label); |
| 407 // Use the shared ToBoolean stub to compile the value in the register into | 370 // Use the shared ToBoolean stub to compile the value in the register into |
| 408 // control flow to the code generator's true and false labels. Perform | 371 // control flow to the code generator's true and false labels. Perform |
| 409 // the fast checks assumed by the stub. | 372 // the fast checks assumed by the stub. |
| 410 | 373 |
| 411 // The undefined value is false. | 374 // The undefined value is false. |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 } | 484 } |
| 522 | 485 |
| 523 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 486 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 524 __ call(ic, RelocInfo::CODE_TARGET); | 487 __ call(ic, RelocInfo::CODE_TARGET); |
| 525 | 488 |
| 526 // Absence of a test rax instruction following the call | 489 // Absence of a test rax instruction following the call |
| 527 // indicates that none of the load was inlined. | 490 // indicates that none of the load was inlined. |
| 528 | 491 |
| 529 // Value in rax is ignored (declarations are statements). Receiver | 492 // Value in rax is ignored (declarations are statements). Receiver |
| 530 // and key on stack are discarded. | 493 // and key on stack are discarded. |
| 531 __ addq(rsp, Immediate(2 * kPointerSize)); | 494 __ Drop(2); |
| 532 } | 495 } |
| 533 } | 496 } |
| 534 } | 497 } |
| 535 | 498 |
| 536 | 499 |
| 537 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 500 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 538 // Call the runtime to declare the globals. | 501 // Call the runtime to declare the globals. |
| 539 __ push(rsi); // The context is the first argument. | 502 __ push(rsi); // The context is the first argument. |
| 540 __ Push(pairs); | 503 __ Push(pairs); |
| 541 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); | 504 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); |
| 542 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 505 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 543 // Return value is ignored. | 506 // Return value is ignored. |
| 544 } | 507 } |
| 545 | 508 |
| 546 | 509 |
| 547 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 510 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 548 Comment cmnt(masm_, "[ FunctionLiteral"); | 511 Comment cmnt(masm_, "[ FunctionLiteral"); |
| 549 | 512 |
| 550 // Build the function boilerplate and instantiate it. | 513 // Build the function boilerplate and instantiate it. |
| 551 Handle<JSFunction> boilerplate = | 514 Handle<JSFunction> boilerplate = |
| 552 Compiler::BuildBoilerplate(expr, script_, this); | 515 Compiler::BuildBoilerplate(expr, script_, this); |
| 553 if (HasStackOverflow()) return; | 516 if (HasStackOverflow()) return; |
| 554 | 517 |
| 555 ASSERT(boilerplate->IsBoilerplate()); | 518 ASSERT(boilerplate->IsBoilerplate()); |
| 556 | 519 |
| 557 // Create a new closure. | 520 // Create a new closure. |
| 558 __ push(rsi); | 521 __ push(rsi); |
| 559 __ Push(boilerplate); | 522 __ Push(boilerplate); |
| 560 __ CallRuntime(Runtime::kNewClosure, 2); | 523 __ CallRuntime(Runtime::kNewClosure, 2); |
| 561 Move(expr->context(), rax); | 524 Apply(expr->context(), rax); |
| 562 } | 525 } |
| 563 | 526 |
| 564 | 527 |
| 565 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 528 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 566 Comment cmnt(masm_, "[ VariableProxy"); | 529 Comment cmnt(masm_, "[ VariableProxy"); |
| 567 EmitVariableLoad(expr->var(), expr->context()); | 530 EmitVariableLoad(expr->var(), expr->context()); |
| 568 } | 531 } |
| 569 | 532 |
| 570 | 533 |
| 571 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 534 void FastCodeGenerator::EmitVariableLoad(Variable* var, |
| 572 Expression::Context context) { | 535 Expression::Context context) { |
| 573 Expression* rewrite = var->rewrite(); | 536 Expression* rewrite = var->rewrite(); |
| 574 if (rewrite == NULL) { | 537 if (rewrite == NULL) { |
| 575 ASSERT(var->is_global()); | 538 ASSERT(var->is_global()); |
| 576 Comment cmnt(masm_, "Global variable"); | 539 Comment cmnt(masm_, "Global variable"); |
| 577 // Use inline caching. Variable name is passed in rcx and the global | 540 // Use inline caching. Variable name is passed in rcx and the global |
| 578 // object on the stack. | 541 // object on the stack. |
| 579 __ push(CodeGenerator::GlobalObject()); | 542 __ push(CodeGenerator::GlobalObject()); |
| 580 __ Move(rcx, var->name()); | 543 __ Move(rcx, var->name()); |
| 581 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 544 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 582 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 545 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 583 // A test rax instruction following the call is used by the IC to | 546 // A test rax instruction following the call is used by the IC to |
| 584 // indicate that the inobject property case was inlined. Ensure there | 547 // indicate that the inobject property case was inlined. Ensure there |
| 585 // is no test rax instruction here. | 548 // is no test rax instruction here. |
| 586 __ nop(); | 549 __ nop(); |
| 587 | 550 |
| 588 DropAndMove(context, rax); | 551 DropAndApply(1, context, rax); |
| 589 } else if (rewrite->AsSlot() != NULL) { | 552 } else if (rewrite->AsSlot() != NULL) { |
| 590 Slot* slot = rewrite->AsSlot(); | 553 Slot* slot = rewrite->AsSlot(); |
| 591 if (FLAG_debug_code) { | 554 if (FLAG_debug_code) { |
| 592 switch (slot->type()) { | 555 switch (slot->type()) { |
| 593 case Slot::LOCAL: | 556 case Slot::LOCAL: |
| 594 case Slot::PARAMETER: { | 557 case Slot::PARAMETER: { |
| 595 Comment cmnt(masm_, "Stack slot"); | 558 Comment cmnt(masm_, "Stack slot"); |
| 596 break; | 559 break; |
| 597 } | 560 } |
| 598 case Slot::CONTEXT: { | 561 case Slot::CONTEXT: { |
| 599 Comment cmnt(masm_, "Context slot"); | 562 Comment cmnt(masm_, "Context slot"); |
| 600 break; | 563 break; |
| 601 } | 564 } |
| 602 case Slot::LOOKUP: | 565 case Slot::LOOKUP: |
| 603 UNIMPLEMENTED(); | 566 UNIMPLEMENTED(); |
| 604 break; | 567 break; |
| 605 } | 568 } |
| 606 } | 569 } |
| 607 Move(context, slot, rax); | 570 Apply(context, slot, rax); |
| 608 } else { | 571 } else { |
| 609 // A variable has been rewritten into an explicit access to | 572 Comment cmnt(masm_, "Variable rewritten to property"); |
| 610 // an object property. | 573 // A variable has been rewritten into an explicit access to an object |
| 574 // property. |
| 611 Property* property = rewrite->AsProperty(); | 575 Property* property = rewrite->AsProperty(); |
| 612 ASSERT_NOT_NULL(property); | 576 ASSERT_NOT_NULL(property); |
| 613 | 577 |
| 614 // Currently the only parameter expressions that can occur are | 578 // The only property expressions that can occur are of the form |
| 615 // on the form "slot[literal]". | 579 // "slot[literal]". |
| 616 | 580 |
| 617 // Check that the object is in a slot. | 581 // Assert that the object is in a slot. |
| 618 Variable* object = property->obj()->AsVariableProxy()->AsVariable(); | 582 Variable* object = property->obj()->AsVariableProxy()->AsVariable(); |
| 619 ASSERT_NOT_NULL(object); | 583 ASSERT_NOT_NULL(object); |
| 620 Slot* object_slot = object->slot(); | 584 Slot* object_slot = object->slot(); |
| 621 ASSERT_NOT_NULL(object_slot); | 585 ASSERT_NOT_NULL(object_slot); |
| 622 | 586 |
| 623 // Load the object. | 587 // Load the object. |
| 624 Move(Expression::kValue, object_slot, rax); | 588 MemOperand object_loc = EmitSlotSearch(object_slot, rax); |
| 589 __ push(object_loc); |
| 625 | 590 |
| 626 // Check that the key is a smi. | 591 // Assert that the key is a smi. |
| 627 Literal* key_literal = property->key()->AsLiteral(); | 592 Literal* key_literal = property->key()->AsLiteral(); |
| 628 ASSERT_NOT_NULL(key_literal); | 593 ASSERT_NOT_NULL(key_literal); |
| 629 ASSERT(key_literal->handle()->IsSmi()); | 594 ASSERT(key_literal->handle()->IsSmi()); |
| 630 | 595 |
| 631 // Load the key. | 596 // Load the key. |
| 632 Move(Expression::kValue, key_literal); | 597 __ Push(key_literal->handle()); |
| 633 | 598 |
| 634 // Do a KEYED property load. | 599 // Do a keyed property load. |
| 635 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 600 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 636 __ call(ic, RelocInfo::CODE_TARGET); | 601 __ call(ic, RelocInfo::CODE_TARGET); |
| 637 // Notice: We must not have a "test rax, ..." instruction after | 602 // Notice: We must not have a "test rax, ..." instruction after the |
| 638 // the call. It is treated specially by the LoadIC code. | 603 // call. It is treated specially by the LoadIC code. |
| 639 | 604 |
| 640 // Drop key and object left on the stack by IC, and push the result. | 605 // Drop key and object left on the stack by IC, and push the result. |
| 641 DropAndMove(context, rax, 2); | 606 DropAndApply(2, context, rax); |
| 642 } | 607 } |
| 643 } | 608 } |
| 644 | 609 |
| 645 | 610 |
| 646 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 611 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 647 Comment cmnt(masm_, "[ RegExpLiteral"); | 612 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 648 Label done; | 613 Label done; |
| 649 // Registers will be used as follows: | 614 // Registers will be used as follows: |
| 650 // rdi = JS function. | 615 // rdi = JS function. |
| 651 // rbx = literals array. | 616 // rbx = literals array. |
| 652 // rax = regexp literal. | 617 // rax = regexp literal. |
| 653 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 618 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 654 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 619 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
| 655 int literal_offset = | 620 int literal_offset = |
| 656 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 621 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 657 __ movq(rax, FieldOperand(rbx, literal_offset)); | 622 __ movq(rax, FieldOperand(rbx, literal_offset)); |
| 658 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 623 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 659 __ j(not_equal, &done); | 624 __ j(not_equal, &done); |
| 660 // Create regexp literal using runtime function | 625 // Create regexp literal using runtime function |
| 661 // Result will be in rax. | 626 // Result will be in rax. |
| 662 __ push(rbx); | 627 __ push(rbx); |
| 663 __ Push(Smi::FromInt(expr->literal_index())); | 628 __ Push(Smi::FromInt(expr->literal_index())); |
| 664 __ Push(expr->pattern()); | 629 __ Push(expr->pattern()); |
| 665 __ Push(expr->flags()); | 630 __ Push(expr->flags()); |
| 666 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 631 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 667 // Label done: | 632 // Label done: |
| 668 __ bind(&done); | 633 __ bind(&done); |
| 669 Move(expr->context(), rax); | 634 Apply(expr->context(), rax); |
| 670 } | 635 } |
| 671 | 636 |
| 672 | 637 |
| 673 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 638 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 674 Comment cmnt(masm_, "[ ObjectLiteral"); | 639 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 675 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 640 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 676 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 641 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
| 677 __ Push(Smi::FromInt(expr->literal_index())); | 642 __ Push(Smi::FromInt(expr->literal_index())); |
| 678 __ Push(expr->constant_properties()); | 643 __ Push(expr->constant_properties()); |
| 679 if (expr->depth() > 1) { | 644 if (expr->depth() > 1) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 __ CallRuntime(Runtime::kDefineAccessor, 4); | 700 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 736 __ movq(rax, Operand(rsp, 0)); // Restore result into rax. | 701 __ movq(rax, Operand(rsp, 0)); // Restore result into rax. |
| 737 break; | 702 break; |
| 738 default: UNREACHABLE(); | 703 default: UNREACHABLE(); |
| 739 } | 704 } |
| 740 } | 705 } |
| 741 switch (expr->context()) { | 706 switch (expr->context()) { |
| 742 case Expression::kUninitialized: | 707 case Expression::kUninitialized: |
| 743 UNREACHABLE(); | 708 UNREACHABLE(); |
| 744 case Expression::kEffect: | 709 case Expression::kEffect: |
| 745 if (result_saved) __ addq(rsp, Immediate(kPointerSize)); | 710 if (result_saved) __ Drop(1); |
| 746 break; | 711 break; |
| 747 case Expression::kValue: | 712 case Expression::kValue: |
| 748 if (!result_saved) __ push(rax); | 713 if (!result_saved) __ push(rax); |
| 749 break; | 714 break; |
| 750 case Expression::kTest: | 715 case Expression::kTest: |
| 751 if (result_saved) __ pop(rax); | 716 if (result_saved) __ pop(rax); |
| 752 TestAndBranch(rax, true_label_, false_label_); | 717 TestAndBranch(rax, true_label_, false_label_); |
| 753 break; | 718 break; |
| 754 case Expression::kValueTest: { | 719 case Expression::kValueTest: { |
| 755 Label discard; | 720 Label discard; |
| 756 if (!result_saved) __ push(rax); | 721 if (!result_saved) __ push(rax); |
| 757 TestAndBranch(rax, true_label_, &discard); | 722 TestAndBranch(rax, true_label_, &discard); |
| 758 __ bind(&discard); | 723 __ bind(&discard); |
| 759 __ addq(rsp, Immediate(kPointerSize)); | 724 __ Drop(1); |
| 760 __ jmp(false_label_); | 725 __ jmp(false_label_); |
| 761 break; | 726 break; |
| 762 } | 727 } |
| 763 case Expression::kTestValue: { | 728 case Expression::kTestValue: { |
| 764 Label discard; | 729 Label discard; |
| 765 if (!result_saved) __ push(rax); | 730 if (!result_saved) __ push(rax); |
| 766 TestAndBranch(rax, &discard, false_label_); | 731 TestAndBranch(rax, &discard, false_label_); |
| 767 __ bind(&discard); | 732 __ bind(&discard); |
| 768 __ addq(rsp, Immediate(kPointerSize)); | 733 __ Drop(1); |
| 769 __ jmp(true_label_); | 734 __ jmp(true_label_); |
| 770 break; | 735 break; |
| 771 } | 736 } |
| 772 } | 737 } |
| 773 } | 738 } |
| 774 | 739 |
| 775 | 740 |
| 776 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 741 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 777 Comment cmnt(masm_, "[ ArrayLiteral"); | 742 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 778 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 743 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 814 __ movq(FieldOperand(rbx, offset), rax); | 779 __ movq(FieldOperand(rbx, offset), rax); |
| 815 | 780 |
| 816 // Update the write barrier for the array store. | 781 // Update the write barrier for the array store. |
| 817 __ RecordWrite(rbx, offset, rax, rcx); | 782 __ RecordWrite(rbx, offset, rax, rcx); |
| 818 } | 783 } |
| 819 | 784 |
| 820 switch (expr->context()) { | 785 switch (expr->context()) { |
| 821 case Expression::kUninitialized: | 786 case Expression::kUninitialized: |
| 822 UNREACHABLE(); | 787 UNREACHABLE(); |
| 823 case Expression::kEffect: | 788 case Expression::kEffect: |
| 824 if (result_saved) __ addq(rsp, Immediate(kPointerSize)); | 789 if (result_saved) __ Drop(1); |
| 825 break; | 790 break; |
| 826 case Expression::kValue: | 791 case Expression::kValue: |
| 827 if (!result_saved) __ push(rax); | 792 if (!result_saved) __ push(rax); |
| 828 break; | 793 break; |
| 829 case Expression::kTest: | 794 case Expression::kTest: |
| 830 if (result_saved) __ pop(rax); | 795 if (result_saved) __ pop(rax); |
| 831 TestAndBranch(rax, true_label_, false_label_); | 796 TestAndBranch(rax, true_label_, false_label_); |
| 832 break; | 797 break; |
| 833 case Expression::kValueTest: { | 798 case Expression::kValueTest: { |
| 834 Label discard; | 799 Label discard; |
| 835 if (!result_saved) __ push(rax); | 800 if (!result_saved) __ push(rax); |
| 836 TestAndBranch(rax, true_label_, &discard); | 801 TestAndBranch(rax, true_label_, &discard); |
| 837 __ bind(&discard); | 802 __ bind(&discard); |
| 838 __ addq(rsp, Immediate(kPointerSize)); | 803 __ Drop(1); |
| 839 __ jmp(false_label_); | 804 __ jmp(false_label_); |
| 840 break; | 805 break; |
| 841 } | 806 } |
| 842 case Expression::kTestValue: { | 807 case Expression::kTestValue: { |
| 843 Label discard; | 808 Label discard; |
| 844 if (!result_saved) __ push(rax); | 809 if (!result_saved) __ push(rax); |
| 845 TestAndBranch(rax, &discard, false_label_); | 810 TestAndBranch(rax, &discard, false_label_); |
| 846 __ bind(&discard); | 811 __ bind(&discard); |
| 847 __ addq(rsp, Immediate(kPointerSize)); | 812 __ Drop(1); |
| 848 __ jmp(true_label_); | 813 __ jmp(true_label_); |
| 849 break; | 814 break; |
| 850 } | 815 } |
| 851 } | 816 } |
| 852 } | 817 } |
| 853 | 818 |
| 854 | 819 |
| 855 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, | 820 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, |
| 856 Expression::Context context) { | 821 Expression::Context context) { |
| 857 SetSourcePosition(prop->position()); | 822 SetSourcePosition(prop->position()); |
| 858 Literal* key = prop->key()->AsLiteral(); | 823 Literal* key = prop->key()->AsLiteral(); |
| 859 __ Move(rcx, key->handle()); | 824 __ Move(rcx, key->handle()); |
| 860 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 825 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 861 __ Call(ic, RelocInfo::CODE_TARGET); | 826 __ Call(ic, RelocInfo::CODE_TARGET); |
| 862 Move(context, rax); | 827 Apply(context, rax); |
| 863 } | 828 } |
| 864 | 829 |
| 865 | 830 |
| 866 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, | 831 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, |
| 867 Expression::Context context) { | 832 Expression::Context context) { |
| 868 SetSourcePosition(prop->position()); | 833 SetSourcePosition(prop->position()); |
| 869 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 834 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 870 __ Call(ic, RelocInfo::CODE_TARGET); | 835 __ Call(ic, RelocInfo::CODE_TARGET); |
| 871 Move(context, rax); | 836 Apply(context, rax); |
| 872 } | 837 } |
| 873 | 838 |
| 874 | 839 |
| 875 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, | 840 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, |
| 876 Expression::Context context) { | 841 Expression::Context context) { |
| 877 GenericBinaryOpStub stub(op, | 842 GenericBinaryOpStub stub(op, |
| 878 NO_OVERWRITE, | 843 NO_OVERWRITE, |
| 879 NO_GENERIC_BINARY_FLAGS); | 844 NO_GENERIC_BINARY_FLAGS); |
| 880 __ CallStub(&stub); | 845 __ CallStub(&stub); |
| 881 Move(context, rax); | 846 Apply(context, rax); |
| 882 } | 847 } |
| 883 | 848 |
| 884 | 849 |
| 885 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 850 void FastCodeGenerator::EmitVariableAssignment(Variable* var, |
| 886 Expression::Context context) { | 851 Expression::Context context) { |
| 887 ASSERT(var != NULL); | 852 ASSERT(var != NULL); |
| 888 ASSERT(var->is_global() || var->slot() != NULL); | 853 ASSERT(var->is_global() || var->slot() != NULL); |
| 889 if (var->is_global()) { | 854 if (var->is_global()) { |
| 890 // Assignment to a global variable. Use inline caching for the | 855 // Assignment to a global variable. Use inline caching for the |
| 891 // assignment. Right-hand-side value is passed in rax, variable name in | 856 // assignment. Right-hand-side value is passed in rax, variable name in |
| 892 // rcx, and the global object on the stack. | 857 // rcx, and the global object on the stack. |
| 893 __ pop(rax); | 858 __ pop(rax); |
| 894 __ Move(rcx, var->name()); | 859 __ Move(rcx, var->name()); |
| 895 __ push(CodeGenerator::GlobalObject()); | 860 __ push(CodeGenerator::GlobalObject()); |
| 896 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 861 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 897 __ Call(ic, RelocInfo::CODE_TARGET); | 862 __ Call(ic, RelocInfo::CODE_TARGET); |
| 898 // Overwrite the global object on the stack with the result if needed. | 863 // Overwrite the global object on the stack with the result if needed. |
| 899 DropAndMove(context, rax); | 864 DropAndApply(1, context, rax); |
| 900 | 865 |
| 901 } else if (var->slot() != NULL) { | 866 } else if (var->slot() != NULL) { |
| 902 Slot* slot = var->slot(); | 867 Slot* slot = var->slot(); |
| 903 switch (slot->type()) { | 868 switch (slot->type()) { |
| 904 case Slot::LOCAL: | 869 case Slot::LOCAL: |
| 905 case Slot::PARAMETER: { | 870 case Slot::PARAMETER: { |
| 906 Operand target = Operand(rbp, SlotOffset(slot)); | 871 Operand target = Operand(rbp, SlotOffset(slot)); |
| 907 switch (context) { | 872 switch (context) { |
| 908 case Expression::kUninitialized: | 873 case Expression::kUninitialized: |
| 909 UNREACHABLE(); | 874 UNREACHABLE(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 921 __ pop(rax); | 886 __ pop(rax); |
| 922 __ movq(target, rax); | 887 __ movq(target, rax); |
| 923 TestAndBranch(rax, true_label_, false_label_); | 888 TestAndBranch(rax, true_label_, false_label_); |
| 924 break; | 889 break; |
| 925 case Expression::kValueTest: { | 890 case Expression::kValueTest: { |
| 926 Label discard; | 891 Label discard; |
| 927 __ movq(rax, Operand(rsp, 0)); | 892 __ movq(rax, Operand(rsp, 0)); |
| 928 __ movq(target, rax); | 893 __ movq(target, rax); |
| 929 TestAndBranch(rax, true_label_, &discard); | 894 TestAndBranch(rax, true_label_, &discard); |
| 930 __ bind(&discard); | 895 __ bind(&discard); |
| 931 __ addq(rsp, Immediate(kPointerSize)); | 896 __ Drop(1); |
| 932 __ jmp(false_label_); | 897 __ jmp(false_label_); |
| 933 break; | 898 break; |
| 934 } | 899 } |
| 935 case Expression::kTestValue: { | 900 case Expression::kTestValue: { |
| 936 Label discard; | 901 Label discard; |
| 937 __ movq(rax, Operand(rsp, 0)); | 902 __ movq(rax, Operand(rsp, 0)); |
| 938 __ movq(target, rax); | 903 __ movq(target, rax); |
| 939 TestAndBranch(rax, &discard, false_label_); | 904 TestAndBranch(rax, &discard, false_label_); |
| 940 __ bind(&discard); | 905 __ bind(&discard); |
| 941 __ addq(rsp, Immediate(kPointerSize)); | 906 __ Drop(1); |
| 942 __ jmp(true_label_); | 907 __ jmp(true_label_); |
| 943 break; | 908 break; |
| 944 } | 909 } |
| 945 } | 910 } |
| 946 break; | 911 break; |
| 947 } | 912 } |
| 948 | 913 |
| 949 case Slot::CONTEXT: { | 914 case Slot::CONTEXT: { |
| 950 MemOperand target = EmitSlotSearch(slot, rcx); | 915 MemOperand target = EmitSlotSearch(slot, rcx); |
| 951 __ pop(rax); | 916 __ pop(rax); |
| 952 __ movq(target, rax); | 917 __ movq(target, rax); |
| 953 | 918 |
| 954 // RecordWrite may destroy all its register arguments. | 919 // RecordWrite may destroy all its register arguments. |
| 955 if (context == Expression::kValue) { | 920 if (context == Expression::kValue) { |
| 956 __ push(rax); | 921 __ push(rax); |
| 957 } else if (context != Expression::kEffect) { | 922 } else if (context != Expression::kEffect) { |
| 958 __ movq(rdx, rax); | 923 __ movq(rdx, rax); |
| 959 } | 924 } |
| 960 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 925 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 961 __ RecordWrite(rcx, offset, rax, rbx); | 926 __ RecordWrite(rcx, offset, rax, rbx); |
| 962 if (context != Expression::kEffect && | 927 if (context != Expression::kEffect && context != Expression::kValue) { |
| 963 context != Expression::kValue) { | 928 Apply(context, rdx); |
| 964 Move(context, rdx); | |
| 965 } | 929 } |
| 966 break; | 930 break; |
| 967 } | 931 } |
| 968 | 932 |
| 969 case Slot::LOOKUP: | 933 case Slot::LOOKUP: |
| 970 UNREACHABLE(); | 934 UNREACHABLE(); |
| 971 break; | 935 break; |
| 972 } | 936 } |
| 973 } else { | 937 } else { |
| 974 // Variables rewritten as properties are not treated as variables in | 938 // Variables rewritten as properties are not treated as variables in |
| (...skipping 23 matching lines...) Expand all Loading... |
| 998 __ Call(ic, RelocInfo::CODE_TARGET); | 962 __ Call(ic, RelocInfo::CODE_TARGET); |
| 999 | 963 |
| 1000 // If the assignment ends an initialization block, revert to fast case. | 964 // If the assignment ends an initialization block, revert to fast case. |
| 1001 if (expr->ends_initialization_block()) { | 965 if (expr->ends_initialization_block()) { |
| 1002 __ push(rax); // Result of assignment, saved even if not needed. | 966 __ push(rax); // Result of assignment, saved even if not needed. |
| 1003 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 967 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
| 1004 __ CallRuntime(Runtime::kToFastProperties, 1); | 968 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1005 __ pop(rax); | 969 __ pop(rax); |
| 1006 } | 970 } |
| 1007 | 971 |
| 1008 DropAndMove(expr->context(), rax); | 972 DropAndApply(1, expr->context(), rax); |
| 1009 } | 973 } |
| 1010 | 974 |
| 1011 | 975 |
| 1012 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 976 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1013 // Assignment to a property, using a keyed store IC. | 977 // Assignment to a property, using a keyed store IC. |
| 1014 | 978 |
| 1015 // If the assignment starts a block of assignments to the same object, | 979 // If the assignment starts a block of assignments to the same object, |
| 1016 // change to slow case to avoid the quadratic behavior of repeatedly | 980 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1017 // adding fast properties. | 981 // adding fast properties. |
| 1018 if (expr->starts_initialization_block()) { | 982 if (expr->starts_initialization_block()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1031 // If the assignment ends an initialization block, revert to fast case. | 995 // If the assignment ends an initialization block, revert to fast case. |
| 1032 if (expr->ends_initialization_block()) { | 996 if (expr->ends_initialization_block()) { |
| 1033 __ push(rax); // Result of assignment, saved even if not needed. | 997 __ push(rax); // Result of assignment, saved even if not needed. |
| 1034 // Reciever is under the key and value. | 998 // Reciever is under the key and value. |
| 1035 __ push(Operand(rsp, 2 * kPointerSize)); | 999 __ push(Operand(rsp, 2 * kPointerSize)); |
| 1036 __ CallRuntime(Runtime::kToFastProperties, 1); | 1000 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1037 __ pop(rax); | 1001 __ pop(rax); |
| 1038 } | 1002 } |
| 1039 | 1003 |
| 1040 // Receiver and key are still on stack. | 1004 // Receiver and key are still on stack. |
| 1041 __ addq(rsp, Immediate(2 * kPointerSize)); | 1005 DropAndApply(2, expr->context(), rax); |
| 1042 Move(expr->context(), rax); | |
| 1043 } | 1006 } |
| 1044 | 1007 |
| 1045 | 1008 |
| 1046 void FastCodeGenerator::VisitProperty(Property* expr) { | 1009 void FastCodeGenerator::VisitProperty(Property* expr) { |
| 1047 Comment cmnt(masm_, "[ Property"); | 1010 Comment cmnt(masm_, "[ Property"); |
| 1048 Expression* key = expr->key(); | 1011 Expression* key = expr->key(); |
| 1049 uint32_t dummy; | |
| 1050 | 1012 |
| 1051 // Record the source position for the property load. | 1013 // Record the source position for the property load. |
| 1052 SetSourcePosition(expr->position()); | 1014 SetSourcePosition(expr->position()); |
| 1053 | 1015 |
| 1054 // Evaluate receiver. | 1016 // Evaluate receiver. |
| 1055 Visit(expr->obj()); | 1017 Visit(expr->obj()); |
| 1056 | 1018 |
| 1057 | 1019 if (key->IsPropertyName()) { |
| 1058 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && | 1020 // Do a named property load. The IC expects the property name in rcx |
| 1059 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { | 1021 // and the receiver on the stack. |
| 1060 // Do a NAMED property load. | |
| 1061 // The IC expects the property name in rcx and the receiver on the stack. | |
| 1062 __ Move(rcx, key->AsLiteral()->handle()); | 1022 __ Move(rcx, key->AsLiteral()->handle()); |
| 1063 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1023 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1064 __ call(ic, RelocInfo::CODE_TARGET); | 1024 __ call(ic, RelocInfo::CODE_TARGET); |
| 1065 // By emitting a nop we make sure that we do not have a "test rax,..." | 1025 // By emitting a nop we make sure that we do not have a "test rax,..." |
| 1066 // instruction after the call it is treated specially by the LoadIC code. | 1026 // instruction after the call it is treated specially by the LoadIC code. |
| 1067 __ nop(); | 1027 __ nop(); |
| 1028 DropAndApply(1, expr->context(), rax); |
| 1068 } else { | 1029 } else { |
| 1069 // Do a KEYED property load. | 1030 // Do a keyed property load. |
| 1070 Visit(expr->key()); | 1031 Visit(expr->key()); |
| 1071 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1032 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1072 __ call(ic, RelocInfo::CODE_TARGET); | 1033 __ call(ic, RelocInfo::CODE_TARGET); |
| 1073 // Notice: We must not have a "test rax, ..." instruction after | 1034 // Notice: We must not have a "test rax, ..." instruction after the |
| 1074 // the call. It is treated specially by the LoadIC code. | 1035 // call. It is treated specially by the LoadIC code. |
| 1075 | 1036 __ nop(); |
| 1076 // Drop key left on the stack by IC. | 1037 // Drop key and receiver left on the stack by IC. |
| 1077 __ addq(rsp, Immediate(kPointerSize)); | 1038 DropAndApply(2, expr->context(), rax); |
| 1078 } | 1039 } |
| 1079 DropAndMove(expr->context(), rax); | |
| 1080 } | 1040 } |
| 1081 | 1041 |
| 1082 | 1042 |
| 1083 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1043 void FastCodeGenerator::EmitCallWithIC(Call* expr, |
| 1084 Handle<Object> ignored, | 1044 Handle<Object> ignored, |
| 1085 RelocInfo::Mode mode) { | 1045 RelocInfo::Mode mode) { |
| 1086 // Code common for calls using the IC. | 1046 // Code common for calls using the IC. |
| 1087 ZoneList<Expression*>* args = expr->arguments(); | 1047 ZoneList<Expression*>* args = expr->arguments(); |
| 1088 int arg_count = args->length(); | 1048 int arg_count = args->length(); |
| 1089 for (int i = 0; i < arg_count; i++) { | 1049 for (int i = 0; i < arg_count; i++) { |
| 1090 Visit(args->at(i)); | 1050 Visit(args->at(i)); |
| 1091 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 1051 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
| 1092 } | 1052 } |
| 1093 // Record source position for debugger. | 1053 // Record source position for debugger. |
| 1094 SetSourcePosition(expr->position()); | 1054 SetSourcePosition(expr->position()); |
| 1095 // Call the IC initialization code. | 1055 // Call the IC initialization code. |
| 1096 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1056 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 1097 NOT_IN_LOOP); | 1057 NOT_IN_LOOP); |
| 1098 __ call(ic, mode); | 1058 __ call(ic, mode); |
| 1099 // Restore context register. | 1059 // Restore context register. |
| 1100 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1060 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1101 // Discard the function left on TOS. | 1061 // Discard the function left on TOS. |
| 1102 DropAndMove(expr->context(), rax); | 1062 DropAndApply(1, expr->context(), rax); |
| 1103 } | 1063 } |
| 1104 | 1064 |
| 1105 | 1065 |
| 1106 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1066 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
| 1107 // Code common for calls using the call stub. | 1067 // Code common for calls using the call stub. |
| 1108 ZoneList<Expression*>* args = expr->arguments(); | 1068 ZoneList<Expression*>* args = expr->arguments(); |
| 1109 int arg_count = args->length(); | 1069 int arg_count = args->length(); |
| 1110 for (int i = 0; i < arg_count; i++) { | 1070 for (int i = 0; i < arg_count; i++) { |
| 1111 Visit(args->at(i)); | 1071 Visit(args->at(i)); |
| 1112 } | 1072 } |
| 1113 // Record source position for debugger. | 1073 // Record source position for debugger. |
| 1114 SetSourcePosition(expr->position()); | 1074 SetSourcePosition(expr->position()); |
| 1115 CallFunctionStub stub(arg_count, NOT_IN_LOOP); | 1075 CallFunctionStub stub(arg_count, NOT_IN_LOOP); |
| 1116 __ CallStub(&stub); | 1076 __ CallStub(&stub); |
| 1117 // Restore context register. | 1077 // Restore context register. |
| 1118 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1078 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1119 // Discard the function left on TOS. | 1079 // Discard the function left on TOS. |
| 1120 DropAndMove(expr->context(), rax); | 1080 DropAndApply(1, expr->context(), rax); |
| 1121 } | 1081 } |
| 1122 | 1082 |
| 1123 | 1083 |
| 1124 void FastCodeGenerator::VisitCall(Call* expr) { | 1084 void FastCodeGenerator::VisitCall(Call* expr) { |
| 1125 Comment cmnt(masm_, "[ Call"); | 1085 Comment cmnt(masm_, "[ Call"); |
| 1126 Expression* fun = expr->expression(); | 1086 Expression* fun = expr->expression(); |
| 1127 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1087 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 1128 | 1088 |
| 1129 if (var != NULL && var->is_possibly_eval()) { | 1089 if (var != NULL && var->is_possibly_eval()) { |
| 1130 // Call to the identifier 'eval'. | 1090 // Call to the identifier 'eval'. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1154 Visit(prop->obj()); | 1114 Visit(prop->obj()); |
| 1155 Visit(prop->key()); | 1115 Visit(prop->key()); |
| 1156 // Record source code position for IC call. | 1116 // Record source code position for IC call. |
| 1157 SetSourcePosition(prop->position()); | 1117 SetSourcePosition(prop->position()); |
| 1158 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1118 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1159 __ call(ic, RelocInfo::CODE_TARGET); | 1119 __ call(ic, RelocInfo::CODE_TARGET); |
| 1160 // By emitting a nop we make sure that we do not have a "test rax,..." | 1120 // By emitting a nop we make sure that we do not have a "test rax,..." |
| 1161 // instruction after the call it is treated specially by the LoadIC code. | 1121 // instruction after the call it is treated specially by the LoadIC code. |
| 1162 __ nop(); | 1122 __ nop(); |
| 1163 // Drop key left on the stack by IC. | 1123 // Drop key left on the stack by IC. |
| 1164 __ addq(rsp, Immediate(kPointerSize)); | 1124 __ Drop(1); |
| 1165 // Pop receiver. | 1125 // Pop receiver. |
| 1166 __ pop(rbx); | 1126 __ pop(rbx); |
| 1167 // Push result (function). | 1127 // Push result (function). |
| 1168 __ push(rax); | 1128 __ push(rax); |
| 1169 // Push receiver object on stack. | 1129 // Push receiver object on stack. |
| 1170 if (prop->is_synthetic()) { | 1130 if (prop->is_synthetic()) { |
| 1171 __ push(CodeGenerator::GlobalObject()); | 1131 __ push(CodeGenerator::GlobalObject()); |
| 1172 } else { | 1132 } else { |
| 1173 __ push(rbx); | 1133 __ push(rbx); |
| 1174 } | 1134 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1223 | 1183 |
| 1224 // Load function, arg_count into rdi and rax. | 1184 // Load function, arg_count into rdi and rax. |
| 1225 __ Set(rax, arg_count); | 1185 __ Set(rax, arg_count); |
| 1226 // Function is in rsp[arg_count + 1]. | 1186 // Function is in rsp[arg_count + 1]. |
| 1227 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); | 1187 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
| 1228 | 1188 |
| 1229 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1189 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
| 1230 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1190 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
| 1231 | 1191 |
| 1232 // Replace function on TOS with result in rax, or pop it. | 1192 // Replace function on TOS with result in rax, or pop it. |
| 1233 DropAndMove(expr->context(), rax); | 1193 DropAndApply(1, expr->context(), rax); |
| 1234 } | 1194 } |
| 1235 | 1195 |
| 1236 | 1196 |
| 1237 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1197 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 1238 Comment cmnt(masm_, "[ CallRuntime"); | 1198 Comment cmnt(masm_, "[ CallRuntime"); |
| 1239 ZoneList<Expression*>* args = expr->arguments(); | 1199 ZoneList<Expression*>* args = expr->arguments(); |
| 1240 | 1200 |
| 1241 if (expr->is_jsruntime()) { | 1201 if (expr->is_jsruntime()) { |
| 1242 // Prepare for calling JS runtime function. | 1202 // Prepare for calling JS runtime function. |
| 1243 __ Push(expr->name()); | 1203 __ Push(expr->name()); |
| 1244 __ movq(rax, CodeGenerator::GlobalObject()); | 1204 __ movq(rax, CodeGenerator::GlobalObject()); |
| 1245 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); | 1205 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); |
| 1246 } | 1206 } |
| 1247 | 1207 |
| 1248 // Push the arguments ("left-to-right"). | 1208 // Push the arguments ("left-to-right"). |
| 1249 int arg_count = args->length(); | 1209 int arg_count = args->length(); |
| 1250 for (int i = 0; i < arg_count; i++) { | 1210 for (int i = 0; i < arg_count; i++) { |
| 1251 Visit(args->at(i)); | 1211 Visit(args->at(i)); |
| 1252 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 1212 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
| 1253 } | 1213 } |
| 1254 | 1214 |
| 1255 if (expr->is_jsruntime()) { | 1215 if (expr->is_jsruntime()) { |
| 1256 // Call the JS runtime function. | 1216 // Call the JS runtime function. |
| 1257 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1217 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 1258 NOT_IN_LOOP); | 1218 NOT_IN_LOOP); |
| 1259 __ call(ic, RelocInfo::CODE_TARGET); | 1219 __ call(ic, RelocInfo::CODE_TARGET); |
| 1260 // Restore context register. | 1220 // Restore context register. |
| 1261 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1221 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1262 // Discard the function left on TOS. | 1222 // Discard the function left on TOS. |
| 1263 DropAndMove(expr->context(), rax); | 1223 DropAndApply(1, expr->context(), rax); |
| 1264 } else { | 1224 } else { |
| 1265 __ CallRuntime(expr->function(), arg_count); | 1225 __ CallRuntime(expr->function(), arg_count); |
| 1266 Move(expr->context(), rax); | 1226 Apply(expr->context(), rax); |
| 1267 } | 1227 } |
| 1268 } | 1228 } |
| 1269 | 1229 |
| 1270 | 1230 |
| 1271 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1231 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 1272 switch (expr->op()) { | 1232 switch (expr->op()) { |
| 1273 case Token::VOID: { | 1233 case Token::VOID: { |
| 1274 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1234 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
| 1275 Visit(expr->expression()); | 1235 Visit(expr->expression()); |
| 1276 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1236 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 __ push(rsi); | 1339 __ push(rsi); |
| 1380 __ Push(proxy->name()); | 1340 __ Push(proxy->name()); |
| 1381 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1341 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 1382 __ push(rax); | 1342 __ push(rax); |
| 1383 } else { | 1343 } else { |
| 1384 // This expression cannot throw a reference error at the top level. | 1344 // This expression cannot throw a reference error at the top level. |
| 1385 Visit(expr->expression()); | 1345 Visit(expr->expression()); |
| 1386 } | 1346 } |
| 1387 | 1347 |
| 1388 __ CallRuntime(Runtime::kTypeof, 1); | 1348 __ CallRuntime(Runtime::kTypeof, 1); |
| 1389 Move(expr->context(), rax); | 1349 Apply(expr->context(), rax); |
| 1390 break; | 1350 break; |
| 1391 } | 1351 } |
| 1392 | 1352 |
| 1393 default: | 1353 default: |
| 1394 UNREACHABLE(); | 1354 UNREACHABLE(); |
| 1395 } | 1355 } |
| 1396 } | 1356 } |
| 1397 | 1357 |
| 1398 | 1358 |
| 1399 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1359 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 // Store the value returned in rax. | 1439 // Store the value returned in rax. |
| 1480 switch (assign_type) { | 1440 switch (assign_type) { |
| 1481 case VARIABLE: | 1441 case VARIABLE: |
| 1482 __ push(rax); | 1442 __ push(rax); |
| 1483 if (expr->is_postfix()) { | 1443 if (expr->is_postfix()) { |
| 1484 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1444 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1485 Expression::kEffect); | 1445 Expression::kEffect); |
| 1486 // For all contexts except kEffect: We have the result on | 1446 // For all contexts except kEffect: We have the result on |
| 1487 // top of the stack. | 1447 // top of the stack. |
| 1488 if (expr->context() != Expression::kEffect) { | 1448 if (expr->context() != Expression::kEffect) { |
| 1489 MoveTOS(expr->context()); | 1449 ApplyTOS(expr->context()); |
| 1490 } | 1450 } |
| 1491 } else { | 1451 } else { |
| 1492 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1452 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1493 expr->context()); | 1453 expr->context()); |
| 1494 } | 1454 } |
| 1495 break; | 1455 break; |
| 1496 case NAMED_PROPERTY: { | 1456 case NAMED_PROPERTY: { |
| 1497 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1457 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
| 1498 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1458 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1499 __ call(ic, RelocInfo::CODE_TARGET); | 1459 __ call(ic, RelocInfo::CODE_TARGET); |
| 1500 // This nop signals to the IC that there is no inlined code at the call | 1460 // This nop signals to the IC that there is no inlined code at the call |
| 1501 // site for it to patch. | 1461 // site for it to patch. |
| 1502 __ nop(); | 1462 __ nop(); |
| 1503 if (expr->is_postfix()) { | 1463 if (expr->is_postfix()) { |
| 1504 __ Drop(1); // Result is on the stack under the receiver. | 1464 __ Drop(1); // Result is on the stack under the receiver. |
| 1505 if (expr->context() != Expression::kEffect) { | 1465 if (expr->context() != Expression::kEffect) { |
| 1506 MoveTOS(expr->context()); | 1466 ApplyTOS(expr->context()); |
| 1507 } | 1467 } |
| 1508 } else { | 1468 } else { |
| 1509 DropAndMove(expr->context(), rax); | 1469 DropAndApply(1, expr->context(), rax); |
| 1510 } | 1470 } |
| 1511 break; | 1471 break; |
| 1512 } | 1472 } |
| 1513 case KEYED_PROPERTY: { | 1473 case KEYED_PROPERTY: { |
| 1514 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1474 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1515 __ call(ic, RelocInfo::CODE_TARGET); | 1475 __ call(ic, RelocInfo::CODE_TARGET); |
| 1516 // This nop signals to the IC that there is no inlined code at the call | 1476 // This nop signals to the IC that there is no inlined code at the call |
| 1517 // site for it to patch. | 1477 // site for it to patch. |
| 1518 __ nop(); | 1478 __ nop(); |
| 1519 if (expr->is_postfix()) { | 1479 if (expr->is_postfix()) { |
| 1520 __ Drop(2); // Result is on the stack under the key and the receiver. | 1480 __ Drop(2); // Result is on the stack under the key and the receiver. |
| 1521 if (expr->context() != Expression::kEffect) { | 1481 if (expr->context() != Expression::kEffect) { |
| 1522 MoveTOS(expr->context()); | 1482 ApplyTOS(expr->context()); |
| 1523 } | 1483 } |
| 1524 } else { | 1484 } else { |
| 1525 DropAndMove(expr->context(), rax, 2); | 1485 DropAndApply(2, expr->context(), rax); |
| 1526 } | 1486 } |
| 1527 break; | 1487 break; |
| 1528 } | 1488 } |
| 1529 } | 1489 } |
| 1530 } | 1490 } |
| 1531 | 1491 |
| 1532 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1492 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 1533 Comment cmnt(masm_, "[ BinaryOperation"); | 1493 Comment cmnt(masm_, "[ BinaryOperation"); |
| 1534 switch (expr->op()) { | 1494 switch (expr->op()) { |
| 1535 case Token::COMMA: | 1495 case Token::COMMA: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1557 case Token::SAR: { | 1517 case Token::SAR: { |
| 1558 ASSERT_EQ(Expression::kValue, expr->left()->context()); | 1518 ASSERT_EQ(Expression::kValue, expr->left()->context()); |
| 1559 ASSERT_EQ(Expression::kValue, expr->right()->context()); | 1519 ASSERT_EQ(Expression::kValue, expr->right()->context()); |
| 1560 | 1520 |
| 1561 Visit(expr->left()); | 1521 Visit(expr->left()); |
| 1562 Visit(expr->right()); | 1522 Visit(expr->right()); |
| 1563 GenericBinaryOpStub stub(expr->op(), | 1523 GenericBinaryOpStub stub(expr->op(), |
| 1564 NO_OVERWRITE, | 1524 NO_OVERWRITE, |
| 1565 NO_GENERIC_BINARY_FLAGS); | 1525 NO_GENERIC_BINARY_FLAGS); |
| 1566 __ CallStub(&stub); | 1526 __ CallStub(&stub); |
| 1567 Move(expr->context(), rax); | 1527 Apply(expr->context(), rax); |
| 1568 | 1528 |
| 1569 break; | 1529 break; |
| 1570 } | 1530 } |
| 1571 default: | 1531 default: |
| 1572 UNREACHABLE(); | 1532 UNREACHABLE(); |
| 1573 } | 1533 } |
| 1574 } | 1534 } |
| 1575 | 1535 |
| 1576 | 1536 |
| 1577 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1537 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1725 break; | 1685 break; |
| 1726 } | 1686 } |
| 1727 true_label_ = saved_true; | 1687 true_label_ = saved_true; |
| 1728 false_label_ = saved_false; | 1688 false_label_ = saved_false; |
| 1729 // Convert current context to test context: End post-test code. | 1689 // Convert current context to test context: End post-test code. |
| 1730 } | 1690 } |
| 1731 | 1691 |
| 1732 | 1692 |
| 1733 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1693 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 1734 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1694 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1735 Move(expr->context(), rax); | 1695 Apply(expr->context(), rax); |
| 1736 } | 1696 } |
| 1737 | 1697 |
| 1738 | 1698 |
| 1739 Register FastCodeGenerator::result_register() { return rax; } | 1699 Register FastCodeGenerator::result_register() { return rax; } |
| 1740 | 1700 |
| 1741 | 1701 |
| 1742 Register FastCodeGenerator::context_register() { return rsi; } | 1702 Register FastCodeGenerator::context_register() { return rsi; } |
| 1743 | 1703 |
| 1744 | 1704 |
| 1745 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1705 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1784 __ movq(Operand(rsp, 0), rdx); | 1744 __ movq(Operand(rsp, 0), rdx); |
| 1785 // And return. | 1745 // And return. |
| 1786 __ ret(0); | 1746 __ ret(0); |
| 1787 } | 1747 } |
| 1788 | 1748 |
| 1789 | 1749 |
| 1790 #undef __ | 1750 #undef __ |
| 1791 | 1751 |
| 1792 | 1752 |
| 1793 } } // namespace v8::internal | 1753 } } // namespace v8::internal |
| OLD | NEW |