Chromium Code Reviews| 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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 #ifdef ENABLE_DEBUGGER_SUPPORT | 187 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 188 // Check that the size of the code used for returning matches what is | 188 // Check that the size of the code used for returning matches what is |
| 189 // expected by the debugger. | 189 // expected by the debugger. |
| 190 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 190 ASSERT_EQ(Assembler::kJSReturnSequenceLength, |
| 191 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 191 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
| 192 #endif | 192 #endif |
| 193 } | 193 } |
| 194 } | 194 } |
| 195 | 195 |
| 196 | 196 |
| 197 void FastCodeGenerator::Move(Expression::Context context, Register source) { | 197 void FastCodeGenerator::Apply(Expression::Context context, |
| 198 Slot* slot, | |
| 199 Register scratch) { | |
|
Lasse Reichstein
2010/01/12 08:30:05
This function looks generic enough that it could b
| |
| 200 switch (context) { | |
| 201 case Expression::kUninitialized: | |
| 202 UNREACHABLE(); | |
| 203 case Expression::kEffect: | |
| 204 break; | |
| 205 case Expression::kValue: { | |
| 206 MemOperand location = EmitSlotSearch(slot, scratch); | |
| 207 __ push(location); | |
| 208 break; | |
| 209 } | |
| 210 case Expression::kTest: | |
| 211 case Expression::kValueTest: | |
| 212 case Expression::kTestValue: | |
| 213 Move(scratch, slot); | |
| 214 Apply(context, scratch); | |
| 215 break; | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 | |
| 220 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { | |
|
Lasse Reichstein
2010/01/12 08:30:05
If we had MacroAssembler::Push(Handle<Object> sour
| |
| 198 switch (context) { | 221 switch (context) { |
| 199 case Expression::kUninitialized: | 222 case Expression::kUninitialized: |
| 200 UNREACHABLE(); | 223 UNREACHABLE(); |
| 201 case Expression::kEffect: | 224 case Expression::kEffect: |
| 202 break; | 225 break; |
| 203 case Expression::kValue: | 226 case Expression::kValue: |
| 204 __ push(source); | 227 __ push(Immediate(lit->handle())); |
| 205 break; | 228 break; |
| 206 case Expression::kTest: | 229 case Expression::kTest: |
| 207 TestAndBranch(source, true_label_, false_label_); | 230 case Expression::kValueTest: |
| 231 case Expression::kTestValue: | |
| 232 __ mov(eax, lit->handle()); | |
| 233 Apply(context, eax); | |
| 208 break; | 234 break; |
| 209 case Expression::kValueTest: { | |
| 210 Label discard; | |
| 211 __ push(source); | |
| 212 TestAndBranch(source, true_label_, &discard); | |
| 213 __ bind(&discard); | |
| 214 __ add(Operand(esp), Immediate(kPointerSize)); | |
| 215 __ jmp(false_label_); | |
| 216 break; | |
| 217 } | |
| 218 case Expression::kTestValue: { | |
| 219 Label discard; | |
| 220 __ push(source); | |
| 221 TestAndBranch(source, &discard, false_label_); | |
| 222 __ bind(&discard); | |
| 223 __ add(Operand(esp), Immediate(kPointerSize)); | |
| 224 __ jmp(true_label_); | |
| 225 } | |
| 226 } | 235 } |
| 227 } | 236 } |
| 228 | 237 |
| 229 | 238 |
| 230 void FastCodeGenerator::MoveTOS(Expression::Context context) { | 239 void FastCodeGenerator::ApplyTOS(Expression::Context context) { |
| 231 switch (context) { | 240 switch (context) { |
| 232 case Expression::kUninitialized: | 241 case Expression::kUninitialized: |
| 233 UNREACHABLE(); | 242 UNREACHABLE(); |
| 234 case Expression::kEffect: | 243 case Expression::kEffect: |
| 235 __ Drop(1); | 244 __ Drop(1); |
| 236 break; | 245 break; |
| 237 case Expression::kValue: | 246 case Expression::kValue: |
| 238 break; | 247 break; |
| 239 case Expression::kTest: | 248 case Expression::kTest: |
| 240 __ pop(eax); | 249 __ pop(eax); |
| 241 TestAndBranch(eax, true_label_, false_label_); | 250 TestAndBranch(eax, true_label_, false_label_); |
| 242 break; | 251 break; |
| 243 case Expression::kValueTest: { | 252 case Expression::kValueTest: { |
| 244 Label discard; | 253 Label discard; |
| 245 __ mov(eax, Operand(esp, 0)); | 254 __ mov(eax, Operand(esp, 0)); |
|
Lasse Reichstein
2010/01/12 08:30:05
With a function like MacroAssembler::MoveToStack(i
| |
| 246 TestAndBranch(eax, true_label_, &discard); | 255 TestAndBranch(eax, true_label_, &discard); |
| 247 __ bind(&discard); | 256 __ bind(&discard); |
| 248 __ Drop(1); | 257 __ Drop(1); |
| 249 __ jmp(false_label_); | 258 __ jmp(false_label_); |
| 259 break; | |
| 260 } | |
| 261 case Expression::kTestValue: { | |
| 262 Label discard; | |
| 263 __ mov(eax, Operand(esp, 0)); | |
| 264 TestAndBranch(eax, &discard, false_label_); | |
| 265 __ bind(&discard); | |
| 266 __ Drop(1); | |
| 267 __ jmp(true_label_); | |
| 268 } | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 | |
| 273 void FastCodeGenerator::DropAndApply(int count, | |
| 274 Expression::Context context, | |
| 275 Register reg) { | |
|
Lasse Reichstein
2010/01/12 08:30:05
And this one too!
(A good abstraction of the stack
| |
| 276 ASSERT(count > 0); | |
| 277 ASSERT(!reg.is(esp)); | |
| 278 switch (context) { | |
| 279 case Expression::kUninitialized: | |
| 280 UNREACHABLE(); | |
| 281 case Expression::kEffect: | |
| 282 __ Drop(count); | |
| 283 break; | |
| 284 case Expression::kValue: | |
| 285 if (count > 1) __ Drop(count - 1); | |
| 286 __ mov(Operand(esp, 0), reg); | |
| 287 break; | |
| 288 case Expression::kTest: | |
| 289 __ Drop(count); | |
| 290 TestAndBranch(reg, true_label_, false_label_); | |
| 291 break; | |
| 292 case Expression::kValueTest: { | |
| 293 Label discard; | |
| 294 if (count > 1) __ Drop(count - 1); | |
| 295 __ mov(Operand(esp, 0), reg); | |
| 296 TestAndBranch(reg, true_label_, &discard); | |
| 297 __ bind(&discard); | |
| 298 __ Drop(1); | |
| 299 __ jmp(false_label_); | |
| 250 break; | 300 break; |
| 251 } | 301 } |
| 252 case Expression::kTestValue: { | 302 case Expression::kTestValue: { |
| 253 Label discard; | 303 Label discard; |
| 254 __ mov(eax, Operand(esp, 0)); | 304 if (count > 1) __ Drop(count - 1); |
| 255 TestAndBranch(eax, &discard, false_label_); | 305 __ mov(Operand(esp, 0), reg); |
| 306 TestAndBranch(reg, &discard, false_label_); | |
| 256 __ bind(&discard); | 307 __ bind(&discard); |
| 257 __ Drop(1); | 308 __ Drop(1); |
| 258 __ jmp(true_label_); | 309 __ jmp(true_label_); |
| 310 break; | |
| 259 } | 311 } |
| 260 } | 312 } |
| 261 } | 313 } |
| 262 | 314 |
| 263 | 315 |
| 264 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 316 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
| 265 switch (slot->type()) { | 317 switch (slot->type()) { |
| 266 case Slot::PARAMETER: | 318 case Slot::PARAMETER: |
| 267 case Slot::LOCAL: | 319 case Slot::LOCAL: |
| 268 return Operand(ebp, SlotOffset(slot)); | 320 return Operand(ebp, SlotOffset(slot)); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 279 return Operand(eax, 0); | 331 return Operand(eax, 0); |
| 280 } | 332 } |
| 281 | 333 |
| 282 | 334 |
| 283 void FastCodeGenerator::Move(Register destination, Slot* source) { | 335 void FastCodeGenerator::Move(Register destination, Slot* source) { |
| 284 MemOperand location = EmitSlotSearch(source, destination); | 336 MemOperand location = EmitSlotSearch(source, destination); |
| 285 __ mov(destination, location); | 337 __ mov(destination, location); |
| 286 } | 338 } |
| 287 | 339 |
| 288 | 340 |
| 289 void FastCodeGenerator::Move(Expression::Context context, | |
| 290 Slot* source, | |
| 291 Register scratch) { | |
| 292 switch (context) { | |
| 293 case Expression::kUninitialized: | |
| 294 UNREACHABLE(); | |
| 295 case Expression::kEffect: | |
| 296 break; | |
| 297 case Expression::kValue: { | |
| 298 MemOperand location = EmitSlotSearch(source, scratch); | |
| 299 __ push(location); | |
| 300 break; | |
| 301 } | |
| 302 case Expression::kTest: | |
| 303 case Expression::kValueTest: | |
| 304 case Expression::kTestValue: | |
| 305 Move(scratch, source); | |
| 306 Move(context, scratch); | |
| 307 break; | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 | |
| 312 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { | |
| 313 switch (context) { | |
| 314 case Expression::kUninitialized: | |
| 315 UNREACHABLE(); | |
| 316 case Expression::kEffect: | |
| 317 break; | |
| 318 case Expression::kValue: | |
| 319 __ push(Immediate(expr->handle())); | |
| 320 break; | |
| 321 case Expression::kTest: | |
| 322 case Expression::kValueTest: | |
| 323 case Expression::kTestValue: | |
| 324 __ mov(eax, expr->handle()); | |
| 325 Move(context, eax); | |
| 326 break; | |
| 327 } | |
| 328 } | |
| 329 | |
| 330 | |
| 331 void FastCodeGenerator::Move(Slot* dst, | 341 void FastCodeGenerator::Move(Slot* dst, |
| 332 Register src, | 342 Register src, |
| 333 Register scratch1, | 343 Register scratch1, |
| 334 Register scratch2) { | 344 Register scratch2) { |
| 335 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 345 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 336 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 346 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 337 MemOperand location = EmitSlotSearch(dst, scratch1); | 347 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 338 __ mov(location, src); | 348 __ mov(location, src); |
| 339 // Emit the write barrier code if the location is in the heap. | 349 // Emit the write barrier code if the location is in the heap. |
| 340 if (dst->type() == Slot::CONTEXT) { | 350 if (dst->type() == Slot::CONTEXT) { |
| 341 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | 351 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
| 342 __ RecordWrite(scratch1, offset, src, scratch2); | 352 __ RecordWrite(scratch1, offset, src, scratch2); |
| 343 } | 353 } |
| 344 } | 354 } |
| 345 | 355 |
| 346 | 356 |
| 347 void FastCodeGenerator::DropAndMove(Expression::Context context, | |
| 348 Register source, | |
| 349 int count) { | |
| 350 ASSERT(count > 0); | |
| 351 switch (context) { | |
| 352 case Expression::kUninitialized: | |
| 353 UNREACHABLE(); | |
| 354 case Expression::kEffect: | |
| 355 __ add(Operand(esp), Immediate(count * kPointerSize)); | |
| 356 break; | |
| 357 case Expression::kValue: | |
| 358 if (count > 1) { | |
| 359 __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); | |
| 360 } | |
| 361 __ mov(Operand(esp, 0), source); | |
| 362 break; | |
| 363 case Expression::kTest: | |
| 364 ASSERT(!source.is(esp)); | |
| 365 __ add(Operand(esp), Immediate(count * kPointerSize)); | |
| 366 TestAndBranch(source, true_label_, false_label_); | |
| 367 break; | |
| 368 case Expression::kValueTest: { | |
| 369 Label discard; | |
| 370 if (count > 1) { | |
| 371 __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); | |
| 372 } | |
| 373 __ mov(Operand(esp, 0), source); | |
| 374 TestAndBranch(source, true_label_, &discard); | |
| 375 __ bind(&discard); | |
| 376 __ add(Operand(esp), Immediate(kPointerSize)); | |
| 377 __ jmp(false_label_); | |
| 378 break; | |
| 379 } | |
| 380 case Expression::kTestValue: { | |
| 381 Label discard; | |
| 382 if (count > 1) { | |
| 383 __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); | |
| 384 } | |
| 385 __ mov(Operand(esp, 0), source); | |
| 386 TestAndBranch(source, &discard, false_label_); | |
| 387 __ bind(&discard); | |
| 388 __ add(Operand(esp), Immediate(kPointerSize)); | |
| 389 __ jmp(true_label_); | |
| 390 break; | |
| 391 } | |
| 392 } | |
| 393 } | |
| 394 | |
| 395 | |
| 396 void FastCodeGenerator::TestAndBranch(Register source, | 357 void FastCodeGenerator::TestAndBranch(Register source, |
| 397 Label* true_label, | 358 Label* true_label, |
| 398 Label* false_label) { | 359 Label* false_label) { |
| 399 ASSERT_NE(NULL, true_label); | 360 ASSERT_NE(NULL, true_label); |
| 400 ASSERT_NE(NULL, false_label); | 361 ASSERT_NE(NULL, false_label); |
| 401 // Use the shared ToBoolean stub to compile the value in the register into | 362 // Use the shared ToBoolean stub to compile the value in the register into |
| 402 // control flow to the code generator's true and false labels. Perform | 363 // control flow to the code generator's true and false labels. Perform |
| 403 // the fast checks assumed by the stub. | 364 // the fast checks assumed by the stub. |
| 404 __ cmp(source, Factory::undefined_value()); // The undefined value is false. | 365 __ cmp(source, Factory::undefined_value()); // The undefined value is false. |
| 405 __ j(equal, false_label); | 366 __ j(equal, false_label); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 511 __ Set(eax, Immediate(Factory::the_hole_value())); | 472 __ Set(eax, Immediate(Factory::the_hole_value())); |
| 512 } | 473 } |
| 513 | 474 |
| 514 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 475 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 515 __ call(ic, RelocInfo::CODE_TARGET); | 476 __ call(ic, RelocInfo::CODE_TARGET); |
| 516 // Absence of a test eax instruction following the call | 477 // Absence of a test eax instruction following the call |
| 517 // indicates that none of the load was inlined. | 478 // indicates that none of the load was inlined. |
| 518 | 479 |
| 519 // Value in eax is ignored (declarations are statements). Receiver | 480 // Value in eax is ignored (declarations are statements). Receiver |
| 520 // and key on stack are discarded. | 481 // and key on stack are discarded. |
| 521 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 482 __ Drop(2); |
| 522 } | 483 } |
| 523 } | 484 } |
| 524 } | 485 } |
| 525 | 486 |
| 526 | 487 |
| 527 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 488 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 528 // Call the runtime to declare the globals. | 489 // Call the runtime to declare the globals. |
| 529 __ push(esi); // The context is the first argument. | 490 __ push(esi); // The context is the first argument. |
| 530 __ push(Immediate(pairs)); | 491 __ push(Immediate(pairs)); |
| 531 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); | 492 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); |
| 532 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 493 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 533 // Return value is ignored. | 494 // Return value is ignored. |
| 534 } | 495 } |
| 535 | 496 |
| 536 | 497 |
| 537 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 498 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 538 Comment cmnt(masm_, "[ FunctionLiteral"); | 499 Comment cmnt(masm_, "[ FunctionLiteral"); |
| 539 | 500 |
| 540 // Build the function boilerplate and instantiate it. | 501 // Build the function boilerplate and instantiate it. |
| 541 Handle<JSFunction> boilerplate = | 502 Handle<JSFunction> boilerplate = |
| 542 Compiler::BuildBoilerplate(expr, script_, this); | 503 Compiler::BuildBoilerplate(expr, script_, this); |
| 543 if (HasStackOverflow()) return; | 504 if (HasStackOverflow()) return; |
| 544 | 505 |
| 545 ASSERT(boilerplate->IsBoilerplate()); | 506 ASSERT(boilerplate->IsBoilerplate()); |
| 546 | 507 |
| 547 // Create a new closure. | 508 // Create a new closure. |
| 548 __ push(esi); | 509 __ push(esi); |
| 549 __ push(Immediate(boilerplate)); | 510 __ push(Immediate(boilerplate)); |
| 550 __ CallRuntime(Runtime::kNewClosure, 2); | 511 __ CallRuntime(Runtime::kNewClosure, 2); |
| 551 Move(expr->context(), eax); | 512 Apply(expr->context(), eax); |
| 552 } | 513 } |
| 553 | 514 |
| 554 | 515 |
| 555 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 516 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 556 Comment cmnt(masm_, "[ VariableProxy"); | 517 Comment cmnt(masm_, "[ VariableProxy"); |
| 557 EmitVariableLoad(expr->var(), expr->context()); | 518 EmitVariableLoad(expr->var(), expr->context()); |
| 558 } | 519 } |
| 559 | 520 |
| 560 | 521 |
| 561 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 522 void FastCodeGenerator::EmitVariableLoad(Variable* var, |
| 562 Expression::Context context) { | 523 Expression::Context context) { |
| 563 Expression* rewrite = var->rewrite(); | 524 Expression* rewrite = var->rewrite(); |
| 564 if (rewrite == NULL) { | 525 if (rewrite == NULL) { |
| 565 ASSERT(var->is_global()); | 526 ASSERT(var->is_global()); |
| 566 Comment cmnt(masm_, "Global variable"); | 527 Comment cmnt(masm_, "Global variable"); |
| 567 // Use inline caching. Variable name is passed in ecx and the global | 528 // Use inline caching. Variable name is passed in ecx and the global |
| 568 // object on the stack. | 529 // object on the stack. |
| 569 __ push(CodeGenerator::GlobalObject()); | 530 __ push(CodeGenerator::GlobalObject()); |
| 570 __ mov(ecx, var->name()); | 531 __ mov(ecx, var->name()); |
| 571 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 532 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 572 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 533 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 573 // By emitting a nop we make sure that we do not have a test eax | 534 // By emitting a nop we make sure that we do not have a test eax |
| 574 // instruction after the call it is treated specially by the LoadIC code | 535 // instruction after the call it is treated specially by the LoadIC code |
| 575 // Remember that the assembler may choose to do peephole optimization | 536 // Remember that the assembler may choose to do peephole optimization |
| 576 // (eg, push/pop elimination). | 537 // (eg, push/pop elimination). |
| 577 __ nop(); | 538 __ nop(); |
| 578 DropAndMove(context, eax); | 539 DropAndApply(1, context, eax); |
| 579 } else if (rewrite->AsSlot() != NULL) { | 540 } else if (rewrite->AsSlot() != NULL) { |
| 580 Slot* slot = rewrite->AsSlot(); | 541 Slot* slot = rewrite->AsSlot(); |
| 581 if (FLAG_debug_code) { | 542 if (FLAG_debug_code) { |
| 582 switch (slot->type()) { | 543 switch (slot->type()) { |
| 583 case Slot::PARAMETER: | 544 case Slot::PARAMETER: |
| 584 case Slot::LOCAL: { | 545 case Slot::LOCAL: { |
| 585 Comment cmnt(masm_, "Stack slot"); | 546 Comment cmnt(masm_, "Stack slot"); |
| 586 break; | 547 break; |
| 587 } | 548 } |
| 588 case Slot::CONTEXT: { | 549 case Slot::CONTEXT: { |
| 589 Comment cmnt(masm_, "Context slot"); | 550 Comment cmnt(masm_, "Context slot"); |
| 590 break; | 551 break; |
| 591 } | 552 } |
| 592 case Slot::LOOKUP: | 553 case Slot::LOOKUP: |
| 593 UNIMPLEMENTED(); | 554 UNIMPLEMENTED(); |
| 594 break; | 555 break; |
| 595 } | 556 } |
| 596 } | 557 } |
| 597 Move(context, slot, eax); | 558 Apply(context, slot, eax); |
| 598 } else { | 559 } else { |
| 599 Comment cmnt(masm_, "Variable rewritten to Property"); | 560 Comment cmnt(masm_, "Variable rewritten to property"); |
| 600 // A variable has been rewritten into an explicit access to | 561 // A variable has been rewritten into an explicit access to an object |
| 601 // an object property. | 562 // property. |
| 602 Property* property = rewrite->AsProperty(); | 563 Property* property = rewrite->AsProperty(); |
| 603 ASSERT_NOT_NULL(property); | 564 ASSERT_NOT_NULL(property); |
| 604 | 565 |
| 605 // Currently the only parameter expressions that can occur are | 566 // The only property expressions that can occur are of the form |
| 606 // on the form "slot[literal]". | 567 // "slot[literal]". |
| 607 | 568 |
| 608 // Check that the object is in a slot. | 569 // Assert that the object is in a slot. |
| 609 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); | 570 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); |
| 610 ASSERT_NOT_NULL(object_var); | 571 ASSERT_NOT_NULL(object_var); |
| 611 Slot* object_slot = object_var->slot(); | 572 Slot* object_slot = object_var->slot(); |
| 612 ASSERT_NOT_NULL(object_slot); | 573 ASSERT_NOT_NULL(object_slot); |
| 613 | 574 |
| 614 // Load the object. | 575 // Load the object. |
| 615 Move(Expression::kValue, object_slot, eax); | 576 MemOperand object_loc = EmitSlotSearch(object_slot, eax); |
| 577 __ push(object_loc); | |
| 616 | 578 |
| 617 // Check that the key is a smi. | 579 // Assert that the key is a smi. |
| 618 Literal* key_literal = property->key()->AsLiteral(); | 580 Literal* key_literal = property->key()->AsLiteral(); |
| 619 ASSERT_NOT_NULL(key_literal); | 581 ASSERT_NOT_NULL(key_literal); |
| 620 ASSERT(key_literal->handle()->IsSmi()); | 582 ASSERT(key_literal->handle()->IsSmi()); |
| 621 | 583 |
| 622 // Load the key. | 584 // Load the key. |
| 623 Move(Expression::kValue, key_literal); | 585 __ push(Immediate(key_literal->handle())); |
| 624 | 586 |
| 625 // Do a KEYED property load. | 587 // Do a keyed property load. |
| 626 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 588 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 627 __ call(ic, RelocInfo::CODE_TARGET); | 589 __ call(ic, RelocInfo::CODE_TARGET); |
| 628 // Notice: We must not have a "test eax, ..." instruction after | 590 // Notice: We must not have a "test eax, ..." instruction after the |
| 629 // the call. It is treated specially by the LoadIC code. | 591 // call. It is treated specially by the LoadIC code. |
| 630 __ nop(); | 592 __ nop(); |
|
Lasse Reichstein
2010/01/12 08:30:05
Can we assume that DropAndMove does not start with
| |
| 631 // Drop key and object left on the stack by IC. | 593 // Drop key and object left on the stack by IC. |
| 632 DropAndMove(context, eax, 2); | 594 DropAndApply(2, context, eax); |
| 633 } | 595 } |
| 634 } | 596 } |
| 635 | 597 |
| 636 | 598 |
| 637 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 599 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 638 Comment cmnt(masm_, "[ RegExpLiteral"); | 600 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 639 Label done; | 601 Label done; |
| 640 // Registers will be used as follows: | 602 // Registers will be used as follows: |
| 641 // edi = JS function. | 603 // edi = JS function. |
| 642 // ebx = literals array. | 604 // ebx = literals array. |
| 643 // eax = regexp literal. | 605 // eax = regexp literal. |
| 644 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 606 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 645 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 607 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 646 int literal_offset = | 608 int literal_offset = |
| 647 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 609 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 648 __ mov(eax, FieldOperand(ebx, literal_offset)); | 610 __ mov(eax, FieldOperand(ebx, literal_offset)); |
| 649 __ cmp(eax, Factory::undefined_value()); | 611 __ cmp(eax, Factory::undefined_value()); |
| 650 __ j(not_equal, &done); | 612 __ j(not_equal, &done); |
| 651 // Create regexp literal using runtime function | 613 // Create regexp literal using runtime function |
| 652 // Result will be in eax. | 614 // Result will be in eax. |
| 653 __ push(ebx); | 615 __ push(ebx); |
| 654 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 616 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 655 __ push(Immediate(expr->pattern())); | 617 __ push(Immediate(expr->pattern())); |
| 656 __ push(Immediate(expr->flags())); | 618 __ push(Immediate(expr->flags())); |
| 657 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 619 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 658 // Label done: | 620 // Label done: |
| 659 __ bind(&done); | 621 __ bind(&done); |
| 660 Move(expr->context(), eax); | 622 Apply(expr->context(), eax); |
| 661 } | 623 } |
| 662 | 624 |
| 663 | 625 |
| 664 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 626 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 665 Comment cmnt(masm_, "[ ObjectLiteral"); | 627 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 666 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 628 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 667 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); | 629 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 668 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 630 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 669 __ push(Immediate(expr->constant_properties())); | 631 __ push(Immediate(expr->constant_properties())); |
| 670 if (expr->depth() > 1) { | 632 if (expr->depth() > 1) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 726 __ CallRuntime(Runtime::kDefineAccessor, 4); | 688 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 727 __ mov(eax, Operand(esp, 0)); // Restore result into eax. | 689 __ mov(eax, Operand(esp, 0)); // Restore result into eax. |
| 728 break; | 690 break; |
| 729 default: UNREACHABLE(); | 691 default: UNREACHABLE(); |
| 730 } | 692 } |
| 731 } | 693 } |
| 732 switch (expr->context()) { | 694 switch (expr->context()) { |
| 733 case Expression::kUninitialized: | 695 case Expression::kUninitialized: |
| 734 UNREACHABLE(); | 696 UNREACHABLE(); |
| 735 case Expression::kEffect: | 697 case Expression::kEffect: |
| 736 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); | 698 if (result_saved) __ Drop(1); |
| 737 break; | 699 break; |
| 738 case Expression::kValue: | 700 case Expression::kValue: |
| 739 if (!result_saved) __ push(eax); | 701 if (!result_saved) __ push(eax); |
| 740 break; | 702 break; |
| 741 case Expression::kTest: | 703 case Expression::kTest: |
| 742 if (result_saved) __ pop(eax); | 704 if (result_saved) __ pop(eax); |
| 743 TestAndBranch(eax, true_label_, false_label_); | 705 TestAndBranch(eax, true_label_, false_label_); |
| 744 break; | 706 break; |
| 745 case Expression::kValueTest: { | 707 case Expression::kValueTest: { |
| 746 Label discard; | 708 Label discard; |
| 747 if (!result_saved) __ push(eax); | 709 if (!result_saved) __ push(eax); |
| 748 TestAndBranch(eax, true_label_, &discard); | 710 TestAndBranch(eax, true_label_, &discard); |
| 749 __ bind(&discard); | 711 __ bind(&discard); |
| 750 __ add(Operand(esp), Immediate(kPointerSize)); | 712 __ Drop(1); |
| 751 __ jmp(false_label_); | 713 __ jmp(false_label_); |
| 752 break; | 714 break; |
| 753 } | 715 } |
| 754 case Expression::kTestValue: { | 716 case Expression::kTestValue: { |
| 755 Label discard; | 717 Label discard; |
| 756 if (!result_saved) __ push(eax); | 718 if (!result_saved) __ push(eax); |
| 757 TestAndBranch(eax, &discard, false_label_); | 719 TestAndBranch(eax, &discard, false_label_); |
| 758 __ bind(&discard); | 720 __ bind(&discard); |
| 759 __ add(Operand(esp), Immediate(kPointerSize)); | 721 __ Drop (1); |
| 760 __ jmp(true_label_); | 722 __ jmp(true_label_); |
| 761 break; | 723 break; |
| 762 } | 724 } |
| 763 } | 725 } |
| 764 } | 726 } |
| 765 | 727 |
| 766 | 728 |
| 767 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 729 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 768 Comment cmnt(masm_, "[ ArrayLiteral"); | 730 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 769 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 731 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 805 __ mov(FieldOperand(ebx, offset), eax); | 767 __ mov(FieldOperand(ebx, offset), eax); |
| 806 | 768 |
| 807 // Update the write barrier for the array store. | 769 // Update the write barrier for the array store. |
| 808 __ RecordWrite(ebx, offset, eax, ecx); | 770 __ RecordWrite(ebx, offset, eax, ecx); |
| 809 } | 771 } |
| 810 | 772 |
| 811 switch (expr->context()) { | 773 switch (expr->context()) { |
| 812 case Expression::kUninitialized: | 774 case Expression::kUninitialized: |
| 813 UNREACHABLE(); | 775 UNREACHABLE(); |
| 814 case Expression::kEffect: | 776 case Expression::kEffect: |
| 815 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); | 777 if (result_saved) __ Drop(1); |
| 816 break; | 778 break; |
| 817 case Expression::kValue: | 779 case Expression::kValue: |
| 818 if (!result_saved) __ push(eax); | 780 if (!result_saved) __ push(eax); |
| 819 break; | 781 break; |
| 820 case Expression::kTest: | 782 case Expression::kTest: |
| 821 if (result_saved) __ pop(eax); | 783 if (result_saved) __ pop(eax); |
| 822 TestAndBranch(eax, true_label_, false_label_); | 784 TestAndBranch(eax, true_label_, false_label_); |
| 823 break; | 785 break; |
| 824 case Expression::kValueTest: { | 786 case Expression::kValueTest: { |
| 825 Label discard; | 787 Label discard; |
| 826 if (!result_saved) __ push(eax); | 788 if (!result_saved) __ push(eax); |
| 827 TestAndBranch(eax, true_label_, &discard); | 789 TestAndBranch(eax, true_label_, &discard); |
| 828 __ bind(&discard); | 790 __ bind(&discard); |
| 829 __ add(Operand(esp), Immediate(kPointerSize)); | 791 __ Drop(1); |
| 830 __ jmp(false_label_); | 792 __ jmp(false_label_); |
| 831 break; | 793 break; |
| 832 } | 794 } |
| 833 case Expression::kTestValue: { | 795 case Expression::kTestValue: { |
| 834 Label discard; | 796 Label discard; |
| 835 if (!result_saved) __ push(eax); | 797 if (!result_saved) __ push(eax); |
| 836 TestAndBranch(eax, &discard, false_label_); | 798 TestAndBranch(eax, &discard, false_label_); |
| 837 __ bind(&discard); | 799 __ bind(&discard); |
| 838 __ add(Operand(esp), Immediate(kPointerSize)); | 800 __ Drop(1); |
| 839 __ jmp(true_label_); | 801 __ jmp(true_label_); |
| 840 break; | 802 break; |
| 841 } | 803 } |
| 842 } | 804 } |
| 843 } | 805 } |
| 844 | 806 |
| 845 | 807 |
| 846 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, | 808 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, |
| 847 Expression::Context context) { | 809 Expression::Context context) { |
| 848 SetSourcePosition(prop->position()); | 810 SetSourcePosition(prop->position()); |
| 849 Literal* key = prop->key()->AsLiteral(); | 811 Literal* key = prop->key()->AsLiteral(); |
| 850 __ mov(ecx, Immediate(key->handle())); | 812 __ mov(ecx, Immediate(key->handle())); |
| 851 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 813 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 852 __ call(ic, RelocInfo::CODE_TARGET); | 814 __ call(ic, RelocInfo::CODE_TARGET); |
| 853 Move(context, eax); | 815 Apply(context, eax); |
| 854 } | 816 } |
| 855 | 817 |
| 856 | 818 |
| 857 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, | 819 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, |
| 858 Expression::Context context) { | 820 Expression::Context context) { |
| 859 SetSourcePosition(prop->position()); | 821 SetSourcePosition(prop->position()); |
| 860 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 822 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 861 __ call(ic, RelocInfo::CODE_TARGET); | 823 __ call(ic, RelocInfo::CODE_TARGET); |
| 862 Move(context, eax); | 824 Apply(context, eax); |
| 863 } | 825 } |
| 864 | 826 |
| 865 | 827 |
| 866 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, | 828 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, |
| 867 Expression::Context context) { | 829 Expression::Context context) { |
| 868 GenericBinaryOpStub stub(op, | 830 GenericBinaryOpStub stub(op, |
| 869 NO_OVERWRITE, | 831 NO_OVERWRITE, |
| 870 NO_GENERIC_BINARY_FLAGS); | 832 NO_GENERIC_BINARY_FLAGS); |
| 871 __ CallStub(&stub); | 833 __ CallStub(&stub); |
| 872 Move(context, eax); | 834 Apply(context, eax); |
| 873 } | 835 } |
| 874 | 836 |
| 875 | 837 |
| 876 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 838 void FastCodeGenerator::EmitVariableAssignment(Variable* var, |
| 877 Expression::Context context) { | 839 Expression::Context context) { |
| 878 ASSERT(var != NULL); | 840 ASSERT(var != NULL); |
| 879 ASSERT(var->is_global() || var->slot() != NULL); | 841 ASSERT(var->is_global() || var->slot() != NULL); |
| 880 if (var->is_global()) { | 842 if (var->is_global()) { |
| 881 // Assignment to a global variable. Use inline caching for the | 843 // Assignment to a global variable. Use inline caching for the |
| 882 // assignment. Right-hand-side value is passed in eax, variable name in | 844 // assignment. Right-hand-side value is passed in eax, variable name in |
| 883 // ecx, and the global object on the stack. | 845 // ecx, and the global object on the stack. |
| 884 __ pop(eax); | 846 __ pop(eax); |
| 885 __ mov(ecx, var->name()); | 847 __ mov(ecx, var->name()); |
| 886 __ push(CodeGenerator::GlobalObject()); | 848 __ push(CodeGenerator::GlobalObject()); |
| 887 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 849 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 888 __ call(ic, RelocInfo::CODE_TARGET); | 850 __ call(ic, RelocInfo::CODE_TARGET); |
| 889 // Overwrite the receiver on the stack with the result if needed. | 851 // Overwrite the receiver on the stack with the result if needed. |
| 890 DropAndMove(context, eax); | 852 DropAndApply(1, context, eax); |
| 891 | 853 |
| 892 } else if (var->slot() != NULL) { | 854 } else if (var->slot() != NULL) { |
| 893 Slot* slot = var->slot(); | 855 Slot* slot = var->slot(); |
| 894 switch (slot->type()) { | 856 switch (slot->type()) { |
| 895 case Slot::LOCAL: | 857 case Slot::LOCAL: |
| 896 case Slot::PARAMETER: { | 858 case Slot::PARAMETER: { |
| 897 Operand target = Operand(ebp, SlotOffset(slot)); | 859 Operand target = Operand(ebp, SlotOffset(slot)); |
| 898 switch (context) { | 860 switch (context) { |
| 899 case Expression::kUninitialized: | 861 case Expression::kUninitialized: |
| 900 UNREACHABLE(); | 862 UNREACHABLE(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 912 __ pop(eax); | 874 __ pop(eax); |
| 913 __ mov(target, eax); | 875 __ mov(target, eax); |
| 914 TestAndBranch(eax, true_label_, false_label_); | 876 TestAndBranch(eax, true_label_, false_label_); |
| 915 break; | 877 break; |
| 916 case Expression::kValueTest: { | 878 case Expression::kValueTest: { |
| 917 Label discard; | 879 Label discard; |
| 918 __ mov(eax, Operand(esp, 0)); | 880 __ mov(eax, Operand(esp, 0)); |
| 919 __ mov(target, eax); | 881 __ mov(target, eax); |
| 920 TestAndBranch(eax, true_label_, &discard); | 882 TestAndBranch(eax, true_label_, &discard); |
| 921 __ bind(&discard); | 883 __ bind(&discard); |
| 922 __ add(Operand(esp), Immediate(kPointerSize)); | 884 __ Drop(1); |
| 923 __ jmp(false_label_); | 885 __ jmp(false_label_); |
| 924 break; | 886 break; |
| 925 } | 887 } |
| 926 case Expression::kTestValue: { | 888 case Expression::kTestValue: { |
| 927 Label discard; | 889 Label discard; |
| 928 __ mov(eax, Operand(esp, 0)); | 890 __ mov(eax, Operand(esp, 0)); |
| 929 __ mov(target, eax); | 891 __ mov(target, eax); |
| 930 TestAndBranch(eax, &discard, false_label_); | 892 TestAndBranch(eax, &discard, false_label_); |
| 931 __ bind(&discard); | 893 __ bind(&discard); |
| 932 __ add(Operand(esp), Immediate(kPointerSize)); | 894 __ Drop(1); |
| 933 __ jmp(true_label_); | 895 __ jmp(true_label_); |
| 934 break; | 896 break; |
| 935 } | 897 } |
| 936 } | 898 } |
| 937 break; | 899 break; |
| 938 } | 900 } |
| 939 | 901 |
| 940 case Slot::CONTEXT: { | 902 case Slot::CONTEXT: { |
| 941 MemOperand target = EmitSlotSearch(slot, ecx); | 903 MemOperand target = EmitSlotSearch(slot, ecx); |
| 942 __ pop(eax); | 904 __ pop(eax); |
| 943 __ mov(target, eax); | 905 __ mov(target, eax); |
| 944 | 906 |
| 945 // RecordWrite may destroy all its register arguments. | 907 // RecordWrite may destroy all its register arguments. |
| 946 if (context == Expression::kValue) { | 908 if (context == Expression::kValue) { |
| 947 __ push(eax); | 909 __ push(eax); |
| 948 } else if (context != Expression::kEffect) { | 910 } else if (context != Expression::kEffect) { |
| 949 __ mov(edx, eax); | 911 __ mov(edx, eax); |
| 950 } | 912 } |
| 951 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 913 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 952 __ RecordWrite(ecx, offset, eax, ebx); | 914 __ RecordWrite(ecx, offset, eax, ebx); |
| 953 if (context != Expression::kEffect && | 915 if (context != Expression::kEffect && context != Expression::kValue) { |
| 954 context != Expression::kValue) { | 916 Apply(context, edx); |
| 955 Move(context, edx); | |
| 956 } | 917 } |
| 957 break; | 918 break; |
| 958 } | 919 } |
| 959 | 920 |
| 960 case Slot::LOOKUP: | 921 case Slot::LOOKUP: |
| 961 UNREACHABLE(); | 922 UNREACHABLE(); |
| 962 break; | 923 break; |
| 963 } | 924 } |
| 964 } else { | 925 } else { |
| 965 // Variables rewritten as properties are not treated as variables in | 926 // Variables rewritten as properties are not treated as variables in |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 989 __ call(ic, RelocInfo::CODE_TARGET); | 950 __ call(ic, RelocInfo::CODE_TARGET); |
| 990 | 951 |
| 991 // If the assignment ends an initialization block, revert to fast case. | 952 // If the assignment ends an initialization block, revert to fast case. |
| 992 if (expr->ends_initialization_block()) { | 953 if (expr->ends_initialization_block()) { |
| 993 __ push(eax); // Result of assignment, saved even if not needed. | 954 __ push(eax); // Result of assignment, saved even if not needed. |
| 994 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 955 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
| 995 __ CallRuntime(Runtime::kToFastProperties, 1); | 956 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 996 __ pop(eax); | 957 __ pop(eax); |
| 997 } | 958 } |
| 998 | 959 |
| 999 DropAndMove(expr->context(), eax); | 960 DropAndApply(1, expr->context(), eax); |
| 1000 } | 961 } |
| 1001 | 962 |
| 1002 | 963 |
| 1003 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 964 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1004 // Assignment to a property, using a keyed store IC. | 965 // Assignment to a property, using a keyed store IC. |
| 1005 | 966 |
| 1006 // If the assignment starts a block of assignments to the same object, | 967 // If the assignment starts a block of assignments to the same object, |
| 1007 // change to slow case to avoid the quadratic behavior of repeatedly | 968 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1008 // adding fast properties. | 969 // adding fast properties. |
| 1009 if (expr->starts_initialization_block()) { | 970 if (expr->starts_initialization_block()) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1022 // If the assignment ends an initialization block, revert to fast case. | 983 // If the assignment ends an initialization block, revert to fast case. |
| 1023 if (expr->ends_initialization_block()) { | 984 if (expr->ends_initialization_block()) { |
| 1024 __ push(eax); // Result of assignment, saved even if not needed. | 985 __ push(eax); // Result of assignment, saved even if not needed. |
| 1025 // Reciever is under the key and value. | 986 // Reciever is under the key and value. |
| 1026 __ push(Operand(esp, 2 * kPointerSize)); | 987 __ push(Operand(esp, 2 * kPointerSize)); |
| 1027 __ CallRuntime(Runtime::kToFastProperties, 1); | 988 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1028 __ pop(eax); | 989 __ pop(eax); |
| 1029 } | 990 } |
| 1030 | 991 |
| 1031 // Receiver and key are still on stack. | 992 // Receiver and key are still on stack. |
| 1032 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 993 DropAndApply(2, expr->context(), eax); |
| 1033 Move(expr->context(), eax); | |
| 1034 } | 994 } |
| 1035 | 995 |
| 1036 | 996 |
| 1037 void FastCodeGenerator::VisitProperty(Property* expr) { | 997 void FastCodeGenerator::VisitProperty(Property* expr) { |
| 1038 Comment cmnt(masm_, "[ Property"); | 998 Comment cmnt(masm_, "[ Property"); |
| 1039 Expression* key = expr->key(); | 999 Expression* key = expr->key(); |
| 1040 uint32_t dummy; | |
| 1041 | 1000 |
| 1042 // Record the source position for the property load. | 1001 // Record the source position for the property load. |
| 1043 SetSourcePosition(expr->position()); | 1002 SetSourcePosition(expr->position()); |
| 1044 | 1003 |
| 1045 // Evaluate receiver. | 1004 // Evaluate the receiver. |
| 1046 Visit(expr->obj()); | 1005 Visit(expr->obj()); |
| 1047 | 1006 |
| 1048 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && | 1007 if (key->IsPropertyName()) { |
| 1049 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { | 1008 // Do a named property load. The IC expects the property name in ecx |
| 1050 // Do a NAMED property load. | 1009 // and the receiver on the stack. |
| 1051 // The IC expects the property name in ecx and the receiver on the stack. | |
| 1052 __ mov(ecx, Immediate(key->AsLiteral()->handle())); | 1010 __ mov(ecx, Immediate(key->AsLiteral()->handle())); |
| 1053 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1011 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1054 __ call(ic, RelocInfo::CODE_TARGET); | 1012 __ call(ic, RelocInfo::CODE_TARGET); |
| 1055 // By emitting a nop we make sure that we do not have a test eax | 1013 // By emitting a nop we make sure that we do not have a test eax |
| 1056 // instruction after the call it is treated specially by the LoadIC code. | 1014 // instruction after the call it is treated specially by the LoadIC code. |
| 1057 __ nop(); | 1015 __ nop(); |
| 1016 DropAndApply(1, expr->context(), eax); | |
| 1058 } else { | 1017 } else { |
| 1059 // Do a KEYED property load. | 1018 // Do a keyed property load. |
| 1060 Visit(expr->key()); | 1019 Visit(expr->key()); |
| 1061 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1020 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1062 __ call(ic, RelocInfo::CODE_TARGET); | 1021 __ call(ic, RelocInfo::CODE_TARGET); |
| 1063 // By emitting a nop we make sure that we do not have a "test eax,..." | 1022 // By emitting a nop we make sure that we do not have a "test eax,..." |
| 1064 // instruction after the call it is treated specially by the LoadIC code. | 1023 // instruction after the call it is treated specially by the LoadIC code. |
| 1065 __ nop(); | 1024 __ nop(); |
| 1066 // Drop key left on the stack by IC. | 1025 // Drop key left on the stack by IC. |
| 1067 __ add(Operand(esp), Immediate(kPointerSize)); | 1026 DropAndApply(2, expr->context(), eax); |
| 1068 } | 1027 } |
| 1069 DropAndMove(expr->context(), eax); | |
| 1070 } | 1028 } |
| 1071 | 1029 |
| 1072 | 1030 |
| 1073 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1031 void FastCodeGenerator::EmitCallWithIC(Call* expr, |
| 1074 Handle<Object> name, | 1032 Handle<Object> name, |
| 1075 RelocInfo::Mode mode) { | 1033 RelocInfo::Mode mode) { |
| 1076 // Code common for calls using the IC. | 1034 // Code common for calls using the IC. |
| 1077 ZoneList<Expression*>* args = expr->arguments(); | 1035 ZoneList<Expression*>* args = expr->arguments(); |
| 1078 int arg_count = args->length(); | 1036 int arg_count = args->length(); |
| 1079 for (int i = 0; i < arg_count; i++) { | 1037 for (int i = 0; i < arg_count; i++) { |
| 1080 Visit(args->at(i)); | 1038 Visit(args->at(i)); |
| 1081 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 1039 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
| 1082 } | 1040 } |
| 1083 __ Set(ecx, Immediate(name)); | 1041 __ Set(ecx, Immediate(name)); |
| 1084 // Record source position of the IC call. | 1042 // Record source position of the IC call. |
| 1085 SetSourcePosition(expr->position()); | 1043 SetSourcePosition(expr->position()); |
| 1086 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1044 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1087 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 1045 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
| 1088 __ call(ic, mode); | 1046 __ call(ic, mode); |
| 1089 // Restore context register. | 1047 // Restore context register. |
| 1090 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1048 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1091 Move(expr->context(), eax); | 1049 Apply(expr->context(), eax); |
| 1092 } | 1050 } |
| 1093 | 1051 |
| 1094 | 1052 |
| 1095 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1053 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
| 1096 // Code common for calls using the call stub. | 1054 // Code common for calls using the call stub. |
| 1097 ZoneList<Expression*>* args = expr->arguments(); | 1055 ZoneList<Expression*>* args = expr->arguments(); |
| 1098 int arg_count = args->length(); | 1056 int arg_count = args->length(); |
| 1099 for (int i = 0; i < arg_count; i++) { | 1057 for (int i = 0; i < arg_count; i++) { |
| 1100 Visit(args->at(i)); | 1058 Visit(args->at(i)); |
| 1101 } | 1059 } |
| 1102 // Record source position for debugger. | 1060 // Record source position for debugger. |
| 1103 SetSourcePosition(expr->position()); | 1061 SetSourcePosition(expr->position()); |
| 1104 CallFunctionStub stub(arg_count, NOT_IN_LOOP); | 1062 CallFunctionStub stub(arg_count, NOT_IN_LOOP); |
| 1105 __ CallStub(&stub); | 1063 __ CallStub(&stub); |
| 1106 // Restore context register. | 1064 // Restore context register. |
| 1107 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1065 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1108 DropAndMove(expr->context(), eax); | 1066 DropAndApply(1, expr->context(), eax); |
| 1109 } | 1067 } |
| 1110 | 1068 |
| 1111 | 1069 |
| 1112 void FastCodeGenerator::VisitCall(Call* expr) { | 1070 void FastCodeGenerator::VisitCall(Call* expr) { |
| 1113 Comment cmnt(masm_, "[ Call"); | 1071 Comment cmnt(masm_, "[ Call"); |
| 1114 Expression* fun = expr->expression(); | 1072 Expression* fun = expr->expression(); |
| 1115 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1073 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 1116 | 1074 |
| 1117 if (var != NULL && var->is_possibly_eval()) { | 1075 if (var != NULL && var->is_possibly_eval()) { |
| 1118 // Call to the identifier 'eval'. | 1076 // Call to the identifier 'eval'. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1139 Visit(prop->obj()); | 1097 Visit(prop->obj()); |
| 1140 Visit(prop->key()); | 1098 Visit(prop->key()); |
| 1141 // Record source code position for IC call. | 1099 // Record source code position for IC call. |
| 1142 SetSourcePosition(prop->position()); | 1100 SetSourcePosition(prop->position()); |
| 1143 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1101 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1144 __ call(ic, RelocInfo::CODE_TARGET); | 1102 __ call(ic, RelocInfo::CODE_TARGET); |
| 1145 // By emitting a nop we make sure that we do not have a "test eax,..." | 1103 // By emitting a nop we make sure that we do not have a "test eax,..." |
| 1146 // instruction after the call it is treated specially by the LoadIC code. | 1104 // instruction after the call it is treated specially by the LoadIC code. |
| 1147 __ nop(); | 1105 __ nop(); |
| 1148 // Drop key left on the stack by IC. | 1106 // Drop key left on the stack by IC. |
| 1149 __ add(Operand(esp), Immediate(kPointerSize)); | 1107 __ Drop(1); |
| 1150 // Pop receiver. | 1108 // Pop receiver. |
| 1151 __ pop(ebx); | 1109 __ pop(ebx); |
| 1152 // Push result (function). | 1110 // Push result (function). |
| 1153 __ push(eax); | 1111 __ push(eax); |
| 1154 // Push receiver object on stack. | 1112 // Push receiver object on stack. |
| 1155 if (prop->is_synthetic()) { | 1113 if (prop->is_synthetic()) { |
| 1156 __ push(CodeGenerator::GlobalObject()); | 1114 __ push(CodeGenerator::GlobalObject()); |
| 1157 } else { | 1115 } else { |
| 1158 __ push(ebx); | 1116 __ push(ebx); |
| 1159 } | 1117 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1207 | 1165 |
| 1208 // Load function, arg_count into edi and eax. | 1166 // Load function, arg_count into edi and eax. |
| 1209 __ Set(eax, Immediate(arg_count)); | 1167 __ Set(eax, Immediate(arg_count)); |
| 1210 // Function is in esp[arg_count + 1]. | 1168 // Function is in esp[arg_count + 1]. |
| 1211 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1169 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); |
| 1212 | 1170 |
| 1213 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1171 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
| 1214 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1172 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
| 1215 | 1173 |
| 1216 // Replace function on TOS with result in eax, or pop it. | 1174 // Replace function on TOS with result in eax, or pop it. |
| 1217 DropAndMove(expr->context(), eax); | 1175 DropAndApply(1, expr->context(), eax); |
| 1218 } | 1176 } |
| 1219 | 1177 |
| 1220 | 1178 |
| 1221 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1179 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 1222 Comment cmnt(masm_, "[ CallRuntime"); | 1180 Comment cmnt(masm_, "[ CallRuntime"); |
| 1223 ZoneList<Expression*>* args = expr->arguments(); | 1181 ZoneList<Expression*>* args = expr->arguments(); |
| 1224 | 1182 |
| 1225 if (expr->is_jsruntime()) { | 1183 if (expr->is_jsruntime()) { |
| 1226 // Prepare for calling JS runtime function. | 1184 // Prepare for calling JS runtime function. |
| 1227 __ mov(eax, CodeGenerator::GlobalObject()); | 1185 __ mov(eax, CodeGenerator::GlobalObject()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1240 __ Set(ecx, Immediate(expr->name())); | 1198 __ Set(ecx, Immediate(expr->name())); |
| 1241 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1199 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1242 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 1200 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
| 1243 __ call(ic, RelocInfo::CODE_TARGET); | 1201 __ call(ic, RelocInfo::CODE_TARGET); |
| 1244 // Restore context register. | 1202 // Restore context register. |
| 1245 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1203 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1246 } else { | 1204 } else { |
| 1247 // Call the C runtime function. | 1205 // Call the C runtime function. |
| 1248 __ CallRuntime(expr->function(), arg_count); | 1206 __ CallRuntime(expr->function(), arg_count); |
| 1249 } | 1207 } |
| 1250 Move(expr->context(), eax); | 1208 Apply(expr->context(), eax); |
| 1251 } | 1209 } |
| 1252 | 1210 |
| 1253 | 1211 |
| 1254 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1212 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 1255 switch (expr->op()) { | 1213 switch (expr->op()) { |
| 1256 case Token::VOID: { | 1214 case Token::VOID: { |
| 1257 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1215 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
| 1258 Visit(expr->expression()); | 1216 Visit(expr->expression()); |
| 1259 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1217 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); |
| 1260 switch (expr->context()) { | 1218 switch (expr->context()) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1362 __ push(esi); | 1320 __ push(esi); |
| 1363 __ push(Immediate(proxy->name())); | 1321 __ push(Immediate(proxy->name())); |
| 1364 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1322 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 1365 __ push(eax); | 1323 __ push(eax); |
| 1366 } else { | 1324 } else { |
| 1367 // This expression cannot throw a reference error at the top level. | 1325 // This expression cannot throw a reference error at the top level. |
| 1368 Visit(expr->expression()); | 1326 Visit(expr->expression()); |
| 1369 } | 1327 } |
| 1370 | 1328 |
| 1371 __ CallRuntime(Runtime::kTypeof, 1); | 1329 __ CallRuntime(Runtime::kTypeof, 1); |
| 1372 Move(expr->context(), eax); | 1330 Apply(expr->context(), eax); |
| 1373 break; | 1331 break; |
| 1374 } | 1332 } |
| 1375 | 1333 |
| 1376 default: | 1334 default: |
| 1377 UNREACHABLE(); | 1335 UNREACHABLE(); |
| 1378 } | 1336 } |
| 1379 } | 1337 } |
| 1380 | 1338 |
| 1381 | 1339 |
| 1382 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1340 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1462 // Store the value returned in eax. | 1420 // Store the value returned in eax. |
| 1463 switch (assign_type) { | 1421 switch (assign_type) { |
| 1464 case VARIABLE: | 1422 case VARIABLE: |
| 1465 __ push(eax); | 1423 __ push(eax); |
| 1466 if (expr->is_postfix()) { | 1424 if (expr->is_postfix()) { |
| 1467 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1425 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1468 Expression::kEffect); | 1426 Expression::kEffect); |
| 1469 // For all contexts except kEffect: We have the result on | 1427 // For all contexts except kEffect: We have the result on |
| 1470 // top of the stack. | 1428 // top of the stack. |
| 1471 if (expr->context() != Expression::kEffect) { | 1429 if (expr->context() != Expression::kEffect) { |
| 1472 MoveTOS(expr->context()); | 1430 ApplyTOS(expr->context()); |
| 1473 } | 1431 } |
| 1474 } else { | 1432 } else { |
| 1475 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1433 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1476 expr->context()); | 1434 expr->context()); |
| 1477 } | 1435 } |
| 1478 break; | 1436 break; |
| 1479 case NAMED_PROPERTY: { | 1437 case NAMED_PROPERTY: { |
| 1480 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1438 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1481 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1439 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1482 __ call(ic, RelocInfo::CODE_TARGET); | 1440 __ call(ic, RelocInfo::CODE_TARGET); |
| 1483 // This nop signals to the IC that there is no inlined code at the call | 1441 // This nop signals to the IC that there is no inlined code at the call |
| 1484 // site for it to patch. | 1442 // site for it to patch. |
| 1485 __ nop(); | 1443 __ nop(); |
| 1486 if (expr->is_postfix()) { | 1444 if (expr->is_postfix()) { |
| 1487 __ Drop(1); // Result is on the stack under the receiver. | 1445 __ Drop(1); // Result is on the stack under the receiver. |
| 1488 if (expr->context() != Expression::kEffect) { | 1446 if (expr->context() != Expression::kEffect) { |
| 1489 MoveTOS(expr->context()); | 1447 ApplyTOS(expr->context()); |
| 1490 } | 1448 } |
| 1491 } else { | 1449 } else { |
| 1492 DropAndMove(expr->context(), eax); | 1450 DropAndApply(1, expr->context(), eax); |
| 1493 } | 1451 } |
| 1494 break; | 1452 break; |
| 1495 } | 1453 } |
| 1496 case KEYED_PROPERTY: { | 1454 case KEYED_PROPERTY: { |
| 1497 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1455 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1498 __ call(ic, RelocInfo::CODE_TARGET); | 1456 __ call(ic, RelocInfo::CODE_TARGET); |
| 1499 // This nop signals to the IC that there is no inlined code at the call | 1457 // This nop signals to the IC that there is no inlined code at the call |
| 1500 // site for it to patch. | 1458 // site for it to patch. |
| 1501 __ nop(); | 1459 __ nop(); |
| 1502 if (expr->is_postfix()) { | 1460 if (expr->is_postfix()) { |
| 1503 __ Drop(2); // Result is on the stack under the key and the receiver. | 1461 __ Drop(2); // Result is on the stack under the key and the receiver. |
| 1504 if (expr->context() != Expression::kEffect) { | 1462 if (expr->context() != Expression::kEffect) { |
| 1505 MoveTOS(expr->context()); | 1463 ApplyTOS(expr->context()); |
| 1506 } | 1464 } |
| 1507 } else { | 1465 } else { |
| 1508 DropAndMove(expr->context(), eax, 2); | 1466 DropAndApply(2, expr->context(), eax); |
| 1509 } | 1467 } |
| 1510 break; | 1468 break; |
| 1511 } | 1469 } |
| 1512 } | 1470 } |
| 1513 } | 1471 } |
| 1514 | 1472 |
| 1515 | 1473 |
| 1516 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1474 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 1517 Comment cmnt(masm_, "[ BinaryOperation"); | 1475 Comment cmnt(masm_, "[ BinaryOperation"); |
| 1518 switch (expr->op()) { | 1476 switch (expr->op()) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1541 case Token::SAR: { | 1499 case Token::SAR: { |
| 1542 ASSERT_EQ(Expression::kValue, expr->left()->context()); | 1500 ASSERT_EQ(Expression::kValue, expr->left()->context()); |
| 1543 ASSERT_EQ(Expression::kValue, expr->right()->context()); | 1501 ASSERT_EQ(Expression::kValue, expr->right()->context()); |
| 1544 | 1502 |
| 1545 Visit(expr->left()); | 1503 Visit(expr->left()); |
| 1546 Visit(expr->right()); | 1504 Visit(expr->right()); |
| 1547 GenericBinaryOpStub stub(expr->op(), | 1505 GenericBinaryOpStub stub(expr->op(), |
| 1548 NO_OVERWRITE, | 1506 NO_OVERWRITE, |
| 1549 NO_GENERIC_BINARY_FLAGS); | 1507 NO_GENERIC_BINARY_FLAGS); |
| 1550 __ CallStub(&stub); | 1508 __ CallStub(&stub); |
| 1551 Move(expr->context(), eax); | 1509 Apply(expr->context(), eax); |
| 1552 | 1510 |
| 1553 break; | 1511 break; |
| 1554 } | 1512 } |
| 1555 default: | 1513 default: |
| 1556 UNREACHABLE(); | 1514 UNREACHABLE(); |
| 1557 } | 1515 } |
| 1558 } | 1516 } |
| 1559 | 1517 |
| 1560 | 1518 |
| 1561 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1519 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1712 break; | 1670 break; |
| 1713 } | 1671 } |
| 1714 true_label_ = saved_true; | 1672 true_label_ = saved_true; |
| 1715 false_label_ = saved_false; | 1673 false_label_ = saved_false; |
| 1716 // Convert current context to test context: End post-test code. | 1674 // Convert current context to test context: End post-test code. |
| 1717 } | 1675 } |
| 1718 | 1676 |
| 1719 | 1677 |
| 1720 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1678 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 1721 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1679 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1722 Move(expr->context(), eax); | 1680 Apply(expr->context(), eax); |
| 1723 } | 1681 } |
| 1724 | 1682 |
| 1725 | 1683 |
| 1726 Register FastCodeGenerator::result_register() { return eax; } | 1684 Register FastCodeGenerator::result_register() { return eax; } |
| 1727 | 1685 |
| 1728 | 1686 |
| 1729 Register FastCodeGenerator::context_register() { return esi; } | 1687 Register FastCodeGenerator::context_register() { return esi; } |
| 1730 | 1688 |
| 1731 | 1689 |
| 1732 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1690 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1767 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 1725 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
| 1768 __ mov(Operand(esp, 0), edx); | 1726 __ mov(Operand(esp, 0), edx); |
| 1769 // And return. | 1727 // And return. |
| 1770 __ ret(0); | 1728 __ ret(0); |
| 1771 } | 1729 } |
| 1772 | 1730 |
| 1773 | 1731 |
| 1774 #undef __ | 1732 #undef __ |
| 1775 | 1733 |
| 1776 } } // namespace v8::internal | 1734 } } // namespace v8::internal |
| OLD | NEW |