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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 // mode 1 instruction where there are restrictions on which immediate values | 207 // mode 1 instruction where there are restrictions on which immediate values |
| 208 // can be encoded in the instruction and which immediate values requires | 208 // can be encoded in the instruction and which immediate values requires |
| 209 // use of an additional instruction for moving the immediate to a temporary | 209 // use of an additional instruction for moving the immediate to a temporary |
| 210 // register. | 210 // register. |
| 211 ASSERT_EQ(return_sequence_length, | 211 ASSERT_EQ(return_sequence_length, |
| 212 masm_->InstructionsGeneratedSince(&check_exit_codesize)); | 212 masm_->InstructionsGeneratedSince(&check_exit_codesize)); |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 | 215 |
| 216 | 216 |
| 217 void FastCodeGenerator::Move(Expression::Context context, Register source) { | 217 void FastCodeGenerator::Apply(Expression::Context context, |
| 218 Slot* slot, | |
| 219 Register scratch) { | |
| 218 switch (context) { | 220 switch (context) { |
| 219 case Expression::kUninitialized: | 221 case Expression::kUninitialized: |
| 220 UNREACHABLE(); | 222 UNREACHABLE(); |
| 221 case Expression::kEffect: | 223 case Expression::kEffect: |
| 222 break; | 224 break; |
| 223 case Expression::kValue: | 225 case Expression::kValue: |
| 224 __ push(source); | 226 case Expression::kTest: |
| 227 case Expression::kValueTest: | |
| 228 case Expression::kTestValue: | |
| 229 Move(scratch, slot); | |
| 230 Apply(context, scratch); | |
| 225 break; | 231 break; |
| 226 case Expression::kTest: | |
| 227 TestAndBranch(source, true_label_, false_label_); | |
| 228 break; | |
| 229 case Expression::kValueTest: { | |
| 230 Label discard; | |
| 231 __ push(source); | |
| 232 TestAndBranch(source, true_label_, &discard); | |
| 233 __ bind(&discard); | |
| 234 __ pop(); | |
| 235 __ jmp(false_label_); | |
| 236 break; | |
| 237 } | |
| 238 case Expression::kTestValue: { | |
| 239 Label discard; | |
| 240 __ push(source); | |
| 241 TestAndBranch(source, &discard, false_label_); | |
| 242 __ bind(&discard); | |
| 243 __ pop(); | |
| 244 __ jmp(true_label_); | |
| 245 } | |
| 246 } | 232 } |
| 247 } | 233 } |
| 248 | 234 |
| 249 | 235 |
| 250 void FastCodeGenerator::MoveTOS(Expression::Context context) { | 236 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
| 237 switch (context) { | |
| 238 case Expression::kUninitialized: | |
| 239 UNREACHABLE(); | |
| 240 case Expression::kEffect: | |
| 241 break; | |
| 242 case Expression::kValue: | |
| 243 case Expression::kTest: | |
| 244 case Expression::kValueTest: | |
| 245 case Expression::kTestValue: | |
| 246 __ mov(ip, Operand(lit->handle())); | |
| 247 Apply(context, ip); | |
| 248 break; | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 | |
| 253 void FastCodeGenerator::ApplyTOS(Expression::Context context) { | |
| 251 switch (context) { | 254 switch (context) { |
| 252 case Expression::kUninitialized: | 255 case Expression::kUninitialized: |
| 253 UNREACHABLE(); | 256 UNREACHABLE(); |
| 254 case Expression::kEffect: | 257 case Expression::kEffect: |
| 255 __ Drop(1); | 258 __ Drop(1); |
| 256 break; | 259 break; |
| 257 case Expression::kValue: | 260 case Expression::kValue: |
| 258 break; | 261 break; |
| 259 case Expression::kTest: | 262 case Expression::kTest: |
| 260 __ pop(r0); | 263 __ pop(r0); |
| 261 TestAndBranch(r0, true_label_, false_label_); | 264 TestAndBranch(r0, true_label_, false_label_); |
| 262 break; | 265 break; |
| 263 case Expression::kValueTest: { | 266 case Expression::kValueTest: { |
| 264 Label discard; | 267 Label discard; |
| 265 __ ldr(r0, MemOperand(sp, 0)); | 268 __ ldr(r0, MemOperand(sp, 0)); |
| 266 TestAndBranch(r0, true_label_, &discard); | 269 TestAndBranch(r0, true_label_, &discard); |
| 267 __ bind(&discard); | 270 __ bind(&discard); |
| 268 __ Drop(1); | 271 __ Drop(1); |
| 269 __ jmp(false_label_); | 272 __ jmp(false_label_); |
| 273 break; | |
| 274 } | |
| 275 case Expression::kTestValue: { | |
| 276 Label discard; | |
| 277 __ ldr(r0, MemOperand(sp, 0)); | |
| 278 TestAndBranch(r0, &discard, false_label_); | |
| 279 __ bind(&discard); | |
| 280 __ Drop(1); | |
| 281 __ jmp(true_label_); | |
| 282 } | |
| 283 } | |
| 284 } | |
| 285 | |
| 286 | |
| 287 void FastCodeGenerator::DropAndApply(int count, | |
| 288 Expression::Context context, | |
| 289 Register reg) { | |
| 290 ASSERT(count > 0); | |
| 291 ASSERT(!reg.is(sp)); | |
| 292 switch (context) { | |
| 293 case Expression::kUninitialized: | |
| 294 UNREACHABLE(); | |
| 295 case Expression::kEffect: | |
| 296 __ Drop(count); | |
| 297 break; | |
| 298 case Expression::kValue: | |
| 299 if (count > 1) __ Drop(count - 1); | |
| 300 __ str(reg, MemOperand(sp)); | |
| 301 break; | |
| 302 case Expression::kTest: | |
| 303 __ Drop(count); | |
| 304 TestAndBranch(reg, true_label_, false_label_); | |
| 305 break; | |
| 306 case Expression::kValueTest: { | |
| 307 Label discard; | |
| 308 if (count > 1) __ Drop(count - 1); | |
| 309 __ str(reg, MemOperand(sp)); | |
| 310 TestAndBranch(reg, true_label_, &discard); | |
| 311 __ bind(&discard); | |
| 312 __ Drop(1); | |
| 313 __ jmp(false_label_); | |
| 270 break; | 314 break; |
| 271 } | 315 } |
| 272 case Expression::kTestValue: { | 316 case Expression::kTestValue: { |
| 273 Label discard; | 317 Label discard; |
| 274 __ ldr(r0, MemOperand(sp, 0)); | 318 if (count > 1) __ Drop(count - 1); |
| 275 TestAndBranch(r0, &discard, false_label_); | 319 __ str(reg, MemOperand(sp)); |
| 320 TestAndBranch(reg, &discard, false_label_); | |
| 276 __ bind(&discard); | 321 __ bind(&discard); |
| 277 __ Drop(1); | 322 __ Drop(1); |
| 278 __ jmp(true_label_); | 323 __ jmp(true_label_); |
| 324 break; | |
| 279 } | 325 } |
| 280 } | 326 } |
| 281 } | 327 } |
| 282 | 328 |
| 283 | 329 |
| 284 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 330 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
| 285 switch (slot->type()) { | 331 switch (slot->type()) { |
| 286 case Slot::PARAMETER: | 332 case Slot::PARAMETER: |
| 287 case Slot::LOCAL: | 333 case Slot::LOCAL: |
| 288 return MemOperand(fp, SlotOffset(slot)); | 334 return MemOperand(fp, SlotOffset(slot)); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 301 | 347 |
| 302 | 348 |
| 303 void FastCodeGenerator::Move(Register destination, Slot* source) { | 349 void FastCodeGenerator::Move(Register destination, Slot* source) { |
| 304 // Use destination as scratch. | 350 // Use destination as scratch. |
| 305 MemOperand location = EmitSlotSearch(source, destination); | 351 MemOperand location = EmitSlotSearch(source, destination); |
| 306 __ ldr(destination, location); | 352 __ ldr(destination, location); |
| 307 } | 353 } |
| 308 | 354 |
| 309 | 355 |
| 310 | 356 |
| 311 void FastCodeGenerator::Move(Expression::Context context, | |
| 312 Slot* source, | |
| 313 Register scratch) { | |
| 314 switch (context) { | |
| 315 case Expression::kUninitialized: | |
| 316 UNREACHABLE(); | |
| 317 case Expression::kEffect: | |
| 318 break; | |
| 319 case Expression::kValue: | |
| 320 case Expression::kTest: | |
| 321 case Expression::kValueTest: | |
| 322 case Expression::kTestValue: | |
| 323 Move(scratch, source); | |
| 324 Move(context, scratch); | |
| 325 break; | |
| 326 } | |
| 327 } | |
| 328 | |
| 329 | |
| 330 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { | |
| 331 switch (context) { | |
| 332 case Expression::kUninitialized: | |
| 333 UNREACHABLE(); | |
| 334 case Expression::kEffect: | |
| 335 break; | |
| 336 case Expression::kValue: | |
| 337 case Expression::kTest: | |
| 338 case Expression::kValueTest: | |
| 339 case Expression::kTestValue: | |
| 340 __ mov(ip, Operand(expr->handle())); | |
| 341 Move(context, ip); | |
| 342 break; | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 | |
| 347 void FastCodeGenerator::Move(Slot* dst, | 357 void FastCodeGenerator::Move(Slot* dst, |
| 348 Register src, | 358 Register src, |
| 349 Register scratch1, | 359 Register scratch1, |
| 350 Register scratch2) { | 360 Register scratch2) { |
| 351 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 361 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 352 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 362 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 353 MemOperand location = EmitSlotSearch(dst, scratch1); | 363 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 354 __ str(src, location); | 364 __ str(src, location); |
| 355 // Emit the write barrier code if the location is in the heap. | 365 // Emit the write barrier code if the location is in the heap. |
| 356 if (dst->type() == Slot::CONTEXT) { | 366 if (dst->type() == Slot::CONTEXT) { |
| 357 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); | 367 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); |
| 358 __ RecordWrite(scratch1, scratch2, src); | 368 __ RecordWrite(scratch1, scratch2, src); |
| 359 } | 369 } |
| 360 } | 370 } |
| 361 | 371 |
| 362 | 372 |
| 363 | 373 |
| 364 void FastCodeGenerator::DropAndMove(Expression::Context context, | |
| 365 Register source, | |
| 366 int drop_count) { | |
| 367 ASSERT(drop_count > 0); | |
| 368 switch (context) { | |
| 369 case Expression::kUninitialized: | |
| 370 UNREACHABLE(); | |
| 371 case Expression::kEffect: | |
| 372 __ add(sp, sp, Operand(drop_count * kPointerSize)); | |
| 373 break; | |
| 374 case Expression::kValue: | |
| 375 if (drop_count > 1) { | |
| 376 __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); | |
| 377 } | |
| 378 __ str(source, MemOperand(sp)); | |
| 379 break; | |
| 380 case Expression::kTest: | |
| 381 ASSERT(!source.is(sp)); | |
| 382 __ add(sp, sp, Operand(drop_count * kPointerSize)); | |
| 383 TestAndBranch(source, true_label_, false_label_); | |
| 384 break; | |
| 385 case Expression::kValueTest: { | |
| 386 Label discard; | |
| 387 if (drop_count > 1) { | |
| 388 __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); | |
| 389 } | |
| 390 __ str(source, MemOperand(sp)); | |
| 391 TestAndBranch(source, true_label_, &discard); | |
| 392 __ bind(&discard); | |
| 393 __ pop(); | |
| 394 __ jmp(false_label_); | |
| 395 break; | |
| 396 } | |
| 397 case Expression::kTestValue: { | |
| 398 Label discard; | |
| 399 if (drop_count > 1) { | |
| 400 __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); | |
| 401 } | |
| 402 __ str(source, MemOperand(sp)); | |
| 403 TestAndBranch(source, &discard, false_label_); | |
| 404 __ bind(&discard); | |
| 405 __ pop(); | |
| 406 __ jmp(true_label_); | |
| 407 break; | |
| 408 } | |
| 409 } | |
| 410 } | |
| 411 | |
| 412 | |
| 413 void FastCodeGenerator::TestAndBranch(Register source, | 374 void FastCodeGenerator::TestAndBranch(Register source, |
| 414 Label* true_label, | 375 Label* true_label, |
| 415 Label* false_label) { | 376 Label* false_label) { |
| 416 ASSERT_NE(NULL, true_label); | 377 ASSERT_NE(NULL, true_label); |
| 417 ASSERT_NE(NULL, false_label); | 378 ASSERT_NE(NULL, false_label); |
| 418 // Call the runtime to find the boolean value of the source and then | 379 // Call the runtime to find the boolean value of the source and then |
| 419 // translate it into control flow to the pair of labels. | 380 // translate it into control flow to the pair of labels. |
| 420 __ push(source); | 381 __ push(source); |
| 421 __ CallRuntime(Runtime::kToBool, 1); | 382 __ CallRuntime(Runtime::kToBool, 1); |
| 422 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 383 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 __ pop(r0); | 478 __ pop(r0); |
| 518 } else { | 479 } else { |
| 519 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 480 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
| 520 } | 481 } |
| 521 | 482 |
| 522 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 483 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 523 __ Call(ic, RelocInfo::CODE_TARGET); | 484 __ Call(ic, RelocInfo::CODE_TARGET); |
| 524 | 485 |
| 525 // Value in r0 is ignored (declarations are statements). Receiver | 486 // Value in r0 is ignored (declarations are statements). Receiver |
| 526 // and key on stack are discarded. | 487 // and key on stack are discarded. |
| 527 __ add(sp, sp, Operand(2 * kPointerSize)); | 488 __ Drop(2); |
| 528 } | 489 } |
| 529 } | 490 } |
| 530 } | 491 } |
| 531 | 492 |
| 532 | 493 |
| 533 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 494 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 534 // Call the runtime to declare the globals. | 495 // Call the runtime to declare the globals. |
| 535 // The context is the first argument. | 496 // The context is the first argument. |
| 536 __ mov(r1, Operand(pairs)); | 497 __ mov(r1, Operand(pairs)); |
| 537 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); | 498 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 548 Handle<JSFunction> boilerplate = | 509 Handle<JSFunction> boilerplate = |
| 549 Compiler::BuildBoilerplate(expr, script_, this); | 510 Compiler::BuildBoilerplate(expr, script_, this); |
| 550 if (HasStackOverflow()) return; | 511 if (HasStackOverflow()) return; |
| 551 | 512 |
| 552 ASSERT(boilerplate->IsBoilerplate()); | 513 ASSERT(boilerplate->IsBoilerplate()); |
| 553 | 514 |
| 554 // Create a new closure. | 515 // Create a new closure. |
| 555 __ mov(r0, Operand(boilerplate)); | 516 __ mov(r0, Operand(boilerplate)); |
| 556 __ stm(db_w, sp, cp.bit() | r0.bit()); | 517 __ stm(db_w, sp, cp.bit() | r0.bit()); |
| 557 __ CallRuntime(Runtime::kNewClosure, 2); | 518 __ CallRuntime(Runtime::kNewClosure, 2); |
| 558 Move(expr->context(), r0); | 519 Apply(expr->context(), r0); |
| 559 } | 520 } |
| 560 | 521 |
| 561 | 522 |
| 562 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 523 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 563 Comment cmnt(masm_, "[ VariableProxy"); | 524 Comment cmnt(masm_, "[ VariableProxy"); |
| 564 EmitVariableLoad(expr->var(), expr->context()); | 525 EmitVariableLoad(expr->var(), expr->context()); |
| 565 } | 526 } |
| 566 | 527 |
| 567 | 528 |
| 568 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 529 void FastCodeGenerator::EmitVariableLoad(Variable* var, |
| 569 Expression::Context context) { | 530 Expression::Context context) { |
| 570 Expression* rewrite = var->rewrite(); | 531 Expression* rewrite = var->rewrite(); |
| 571 if (rewrite == NULL) { | 532 if (rewrite == NULL) { |
| 572 ASSERT(var->is_global()); | 533 ASSERT(var->is_global()); |
| 573 Comment cmnt(masm_, "Global variable"); | 534 Comment cmnt(masm_, "Global variable"); |
| 574 // Use inline caching. Variable name is passed in r2 and the global | 535 // Use inline caching. Variable name is passed in r2 and the global |
| 575 // object on the stack. | 536 // object on the stack. |
| 576 __ ldr(ip, CodeGenerator::GlobalObject()); | 537 __ ldr(ip, CodeGenerator::GlobalObject()); |
| 577 __ push(ip); | 538 __ push(ip); |
| 578 __ mov(r2, Operand(var->name())); | 539 __ mov(r2, Operand(var->name())); |
| 579 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 540 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 580 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 541 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 581 DropAndMove(context, r0); | 542 DropAndApply(1, context, r0); |
| 582 } else if (rewrite->AsSlot() != NULL) { | 543 } else if (rewrite->AsSlot() != NULL) { |
| 583 Slot* slot = rewrite->AsSlot(); | 544 Slot* slot = rewrite->AsSlot(); |
| 584 if (FLAG_debug_code) { | 545 if (FLAG_debug_code) { |
| 585 switch (slot->type()) { | 546 switch (slot->type()) { |
| 586 case Slot::PARAMETER: | 547 case Slot::PARAMETER: |
| 587 case Slot::LOCAL: { | 548 case Slot::LOCAL: { |
| 588 Comment cmnt(masm_, "Stack slot"); | 549 Comment cmnt(masm_, "Stack slot"); |
| 589 break; | 550 break; |
| 590 } | 551 } |
| 591 case Slot::CONTEXT: { | 552 case Slot::CONTEXT: { |
| 592 Comment cmnt(masm_, "Context slot"); | 553 Comment cmnt(masm_, "Context slot"); |
| 593 break; | 554 break; |
| 594 } | 555 } |
| 595 case Slot::LOOKUP: | 556 case Slot::LOOKUP: |
| 596 UNIMPLEMENTED(); | 557 UNIMPLEMENTED(); |
| 597 break; | 558 break; |
| 598 } | 559 } |
| 599 } | 560 } |
| 600 Move(context, slot, r0); | 561 Apply(context, slot, r0); |
| 601 } else { | 562 } else { |
| 602 // A variable has been rewritten into an explicit access to | 563 Comment cmnt(masm_, "Variable rewritten to property"); |
| 603 // an object property. | 564 // A variable has been rewritten into an explicit access to an object |
| 565 // property. | |
| 604 Property* property = rewrite->AsProperty(); | 566 Property* property = rewrite->AsProperty(); |
| 605 ASSERT_NOT_NULL(property); | 567 ASSERT_NOT_NULL(property); |
| 606 | 568 |
| 607 // Currently the only parameter expressions that can occur are | 569 // The only property expressions that can occur are of the form |
| 608 // on the form "slot[literal]". | 570 // "slot[literal]". |
| 609 | 571 |
| 610 // Check that the object is in a slot. | 572 // Assert that the object is in a slot. |
| 611 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); | 573 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); |
| 612 ASSERT_NOT_NULL(object_var); | 574 ASSERT_NOT_NULL(object_var); |
| 613 Slot* object_slot = object_var->slot(); | 575 Slot* object_slot = object_var->slot(); |
| 614 ASSERT_NOT_NULL(object_slot); | 576 ASSERT_NOT_NULL(object_slot); |
| 615 | 577 |
| 616 // Load the object. | 578 // Load the object. |
| 617 Move(r2, object_slot); | 579 Move(r2, object_slot); |
| 618 | 580 |
| 619 // Check that the key is a smi. | 581 // Assert that the key is a smi. |
| 620 Literal* key_literal = property->key()->AsLiteral(); | 582 Literal* key_literal = property->key()->AsLiteral(); |
| 621 ASSERT_NOT_NULL(key_literal); | 583 ASSERT_NOT_NULL(key_literal); |
| 622 ASSERT(key_literal->handle()->IsSmi()); | 584 ASSERT(key_literal->handle()->IsSmi()); |
| 623 | 585 |
| 624 // Load the key. | 586 // Load the key. |
| 625 __ mov(r1, Operand(key_literal->handle())); | 587 __ mov(r1, Operand(key_literal->handle())); |
| 626 | 588 |
| 627 // Push both as arguments to ic. | 589 // Push both as arguments to ic. |
| 628 __ stm(db_w, sp, r2.bit() | r1.bit()); | 590 __ stm(db_w, sp, r2.bit() | r1.bit()); |
| 629 | 591 |
| 630 // Do a KEYED property load. | 592 // Do a keyed property load. |
| 631 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 593 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 632 __ Call(ic, RelocInfo::CODE_TARGET); | 594 __ Call(ic, RelocInfo::CODE_TARGET); |
| 633 | 595 |
| 634 // Drop key and object left on the stack by IC, and push the result. | 596 // Drop key and object left on the stack by IC, and push the result. |
| 635 DropAndMove(context, r0, 2); | 597 DropAndApply(2, context, r0); |
| 636 } | 598 } |
| 637 } | 599 } |
| 638 | 600 |
| 639 | 601 |
| 640 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 602 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 641 Comment cmnt(masm_, "[ RegExpLiteral"); | 603 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 642 Label done; | 604 Label done; |
| 643 // Registers will be used as follows: | 605 // Registers will be used as follows: |
| 644 // r4 = JS function, literals array | 606 // r4 = JS function, literals array |
| 645 // r3 = literal index | 607 // r3 = literal index |
| 646 // r2 = RegExp pattern | 608 // r2 = RegExp pattern |
| 647 // r1 = RegExp flags | 609 // r1 = RegExp flags |
| 648 // r0 = temp + return value (RegExp literal) | 610 // r0 = temp + return value (RegExp literal) |
| 649 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 611 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 650 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 612 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
| 651 int literal_offset = | 613 int literal_offset = |
| 652 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 614 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 653 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | 615 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
| 654 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 616 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 655 __ cmp(r0, ip); | 617 __ cmp(r0, ip); |
| 656 __ b(ne, &done); | 618 __ b(ne, &done); |
| 657 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 619 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
| 658 __ mov(r2, Operand(expr->pattern())); | 620 __ mov(r2, Operand(expr->pattern())); |
| 659 __ mov(r1, Operand(expr->flags())); | 621 __ mov(r1, Operand(expr->flags())); |
| 660 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); | 622 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); |
| 661 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 623 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 662 __ bind(&done); | 624 __ bind(&done); |
| 663 Move(expr->context(), r0); | 625 Apply(expr->context(), r0); |
| 664 } | 626 } |
| 665 | 627 |
| 666 | 628 |
| 667 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 629 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 668 Comment cmnt(masm_, "[ ObjectLiteral"); | 630 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 669 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 631 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 670 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 632 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
| 671 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); | 633 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); |
| 672 __ mov(r0, Operand(expr->constant_properties())); | 634 __ mov(r0, Operand(expr->constant_properties())); |
| 673 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); | 635 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 735 ASSERT_EQ(Expression::kValue, value->context()); | 697 ASSERT_EQ(Expression::kValue, value->context()); |
| 736 __ CallRuntime(Runtime::kDefineAccessor, 4); | 698 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 737 __ ldr(r0, MemOperand(sp)); // Restore result into r0 | 699 __ ldr(r0, MemOperand(sp)); // Restore result into r0 |
| 738 break; | 700 break; |
| 739 } | 701 } |
| 740 } | 702 } |
| 741 switch (expr->context()) { | 703 switch (expr->context()) { |
| 742 case Expression::kUninitialized: | 704 case Expression::kUninitialized: |
| 743 UNREACHABLE(); | 705 UNREACHABLE(); |
| 744 case Expression::kEffect: | 706 case Expression::kEffect: |
| 745 if (result_saved) __ pop(); | 707 if (result_saved) __ Drop(1); |
| 746 break; | 708 break; |
| 747 case Expression::kValue: | 709 case Expression::kValue: |
| 748 if (!result_saved) __ push(r0); | 710 if (!result_saved) __ push(r0); |
| 749 break; | 711 break; |
| 750 case Expression::kTest: | 712 case Expression::kTest: |
| 751 if (result_saved) __ pop(r0); | 713 if (result_saved) __ pop(r0); |
| 752 TestAndBranch(r0, true_label_, false_label_); | 714 TestAndBranch(r0, true_label_, false_label_); |
| 753 break; | 715 break; |
| 754 case Expression::kValueTest: { | 716 case Expression::kValueTest: { |
| 755 Label discard; | 717 Label discard; |
| 756 if (!result_saved) __ push(r0); | 718 if (!result_saved) __ push(r0); |
| 757 TestAndBranch(r0, true_label_, &discard); | 719 TestAndBranch(r0, true_label_, &discard); |
| 758 __ bind(&discard); | 720 __ bind(&discard); |
| 759 __ pop(); | 721 __ Drop(1); |
| 760 __ jmp(false_label_); | 722 __ jmp(false_label_); |
| 761 break; | 723 break; |
| 762 } | 724 } |
| 763 case Expression::kTestValue: { | 725 case Expression::kTestValue: { |
| 764 Label discard; | 726 Label discard; |
| 765 if (!result_saved) __ push(r0); | 727 if (!result_saved) __ push(r0); |
| 766 TestAndBranch(r0, &discard, false_label_); | 728 TestAndBranch(r0, &discard, false_label_); |
| 767 __ bind(&discard); | 729 __ bind(&discard); |
| 768 __ pop(); | 730 __ Drop(1); |
| 769 __ jmp(true_label_); | 731 __ jmp(true_label_); |
| 770 break; | 732 break; |
| 771 } | 733 } |
| 772 } | 734 } |
| 773 } | 735 } |
| 774 | 736 |
| 775 | 737 |
| 776 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 738 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 777 Comment cmnt(masm_, "[ ArrayLiteral"); | 739 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 778 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 740 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 775 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
| 814 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 776 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 815 __ str(r0, FieldMemOperand(r1, offset)); | 777 __ str(r0, FieldMemOperand(r1, offset)); |
| 816 | 778 |
| 817 // Update the write barrier for the array store with r0 as the scratch | 779 // Update the write barrier for the array store with r0 as the scratch |
| 818 // register. | 780 // register. |
| 819 __ mov(r2, Operand(offset)); | 781 __ mov(r2, Operand(offset)); |
| 820 __ RecordWrite(r1, r2, r0); | 782 __ RecordWrite(r1, r2, r0); |
| 821 } | 783 } |
| 822 | 784 |
| 823 switch (expr->context()) { | 785 switch (expr->context()) { |
|
Lasse Reichstein
2010/01/12 08:30:05
This switch is identical to the one at line 703. C
| |
| 824 case Expression::kUninitialized: | 786 case Expression::kUninitialized: |
| 825 UNREACHABLE(); | 787 UNREACHABLE(); |
| 826 case Expression::kEffect: | 788 case Expression::kEffect: |
| 827 if (result_saved) __ pop(); | 789 if (result_saved) __ Drop(1); |
| 828 break; | 790 break; |
| 829 case Expression::kValue: | 791 case Expression::kValue: |
| 830 if (!result_saved) __ push(r0); | 792 if (!result_saved) __ push(r0); |
| 831 break; | 793 break; |
| 832 case Expression::kTest: | 794 case Expression::kTest: |
| 833 if (result_saved) __ pop(r0); | 795 if (result_saved) __ pop(r0); |
| 834 TestAndBranch(r0, true_label_, false_label_); | 796 TestAndBranch(r0, true_label_, false_label_); |
| 835 break; | 797 break; |
| 836 case Expression::kValueTest: { | 798 case Expression::kValueTest: { |
| 837 Label discard; | 799 Label discard; |
| 838 if (!result_saved) __ push(r0); | 800 if (!result_saved) __ push(r0); |
| 839 TestAndBranch(r0, true_label_, &discard); | 801 TestAndBranch(r0, true_label_, &discard); |
| 840 __ bind(&discard); | 802 __ bind(&discard); |
| 841 __ pop(); | 803 __ Drop(1); |
| 842 __ jmp(false_label_); | 804 __ jmp(false_label_); |
| 843 break; | 805 break; |
| 844 } | 806 } |
| 845 case Expression::kTestValue: { | 807 case Expression::kTestValue: { |
| 846 Label discard; | 808 Label discard; |
| 847 if (!result_saved) __ push(r0); | 809 if (!result_saved) __ push(r0); |
| 848 TestAndBranch(r0, &discard, false_label_); | 810 TestAndBranch(r0, &discard, false_label_); |
| 849 __ bind(&discard); | 811 __ bind(&discard); |
| 850 __ pop(); | 812 __ Drop(1); |
| 851 __ jmp(true_label_); | 813 __ jmp(true_label_); |
| 852 break; | 814 break; |
| 853 } | 815 } |
| 854 } | 816 } |
| 855 } | 817 } |
| 856 | 818 |
| 857 | 819 |
| 858 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, | 820 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, |
| 859 Expression::Context context) { | 821 Expression::Context context) { |
| 860 SetSourcePosition(prop->position()); | 822 SetSourcePosition(prop->position()); |
| 861 Literal* key = prop->key()->AsLiteral(); | 823 Literal* key = prop->key()->AsLiteral(); |
| 862 __ mov(r2, Operand(key->handle())); | 824 __ mov(r2, Operand(key->handle())); |
| 863 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 825 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 864 __ Call(ic, RelocInfo::CODE_TARGET); | 826 __ Call(ic, RelocInfo::CODE_TARGET); |
| 865 Move(context, r0); | 827 Apply(context, r0); |
| 866 } | 828 } |
| 867 | 829 |
| 868 | 830 |
| 869 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, | 831 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, |
| 870 Expression::Context context) { | 832 Expression::Context context) { |
| 871 SetSourcePosition(prop->position()); | 833 SetSourcePosition(prop->position()); |
| 872 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 834 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 873 __ Call(ic, RelocInfo::CODE_TARGET); | 835 __ Call(ic, RelocInfo::CODE_TARGET); |
| 874 Move(context, r0); | 836 Apply(context, r0); |
| 875 } | 837 } |
| 876 | 838 |
| 877 | 839 |
| 878 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, | 840 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, |
| 879 Expression::Context context) { | 841 Expression::Context context) { |
| 880 __ pop(r0); | 842 __ pop(r0); |
| 881 __ pop(r1); | 843 __ pop(r1); |
| 882 GenericBinaryOpStub stub(op, | 844 GenericBinaryOpStub stub(op, |
| 883 NO_OVERWRITE); | 845 NO_OVERWRITE); |
| 884 __ CallStub(&stub); | 846 __ CallStub(&stub); |
| 885 Move(context, r0); | 847 Apply(context, r0); |
| 886 } | 848 } |
| 887 | 849 |
| 888 | 850 |
| 889 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 851 void FastCodeGenerator::EmitVariableAssignment(Variable* var, |
| 890 Expression::Context context) { | 852 Expression::Context context) { |
| 891 ASSERT(var != NULL); | 853 ASSERT(var != NULL); |
| 892 ASSERT(var->is_global() || var->slot() != NULL); | 854 ASSERT(var->is_global() || var->slot() != NULL); |
| 893 if (var->is_global()) { | 855 if (var->is_global()) { |
| 894 // Assignment to a global variable. Use inline caching for the | 856 // Assignment to a global variable. Use inline caching for the |
| 895 // assignment. Right-hand-side value is passed in r0, variable name in | 857 // assignment. Right-hand-side value is passed in r0, variable name in |
| 896 // r2, and the global object on the stack. | 858 // r2, and the global object on the stack. |
| 897 __ pop(r0); | 859 __ pop(r0); |
| 898 __ mov(r2, Operand(var->name())); | 860 __ mov(r2, Operand(var->name())); |
| 899 __ ldr(ip, CodeGenerator::GlobalObject()); | 861 __ ldr(ip, CodeGenerator::GlobalObject()); |
| 900 __ push(ip); | 862 __ push(ip); |
| 901 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 863 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 902 __ Call(ic, RelocInfo::CODE_TARGET); | 864 __ Call(ic, RelocInfo::CODE_TARGET); |
| 903 // Overwrite the global object on the stack with the result if needed. | 865 // Overwrite the global object on the stack with the result if needed. |
| 904 DropAndMove(context, r0); | 866 DropAndApply(1, context, r0); |
| 905 | 867 |
| 906 } else if (var->slot() != NULL) { | 868 } else if (var->slot() != NULL) { |
| 907 Slot* slot = var->slot(); | 869 Slot* slot = var->slot(); |
| 908 switch (slot->type()) { | 870 switch (slot->type()) { |
| 909 case Slot::LOCAL: | 871 case Slot::LOCAL: |
| 910 case Slot::PARAMETER: { | 872 case Slot::PARAMETER: { |
| 911 MemOperand target = MemOperand(fp, SlotOffset(slot)); | 873 MemOperand target = MemOperand(fp, SlotOffset(slot)); |
| 912 switch (context) { | 874 switch (context) { |
| 913 case Expression::kUninitialized: | 875 case Expression::kUninitialized: |
| 914 UNREACHABLE(); | 876 UNREACHABLE(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 927 __ pop(r0); | 889 __ pop(r0); |
| 928 __ str(r0, target); | 890 __ str(r0, target); |
| 929 TestAndBranch(r0, true_label_, false_label_); | 891 TestAndBranch(r0, true_label_, false_label_); |
| 930 break; | 892 break; |
| 931 case Expression::kValueTest: { | 893 case Expression::kValueTest: { |
| 932 Label discard; | 894 Label discard; |
| 933 __ ldr(r0, MemOperand(sp)); | 895 __ ldr(r0, MemOperand(sp)); |
| 934 __ str(r0, target); | 896 __ str(r0, target); |
| 935 TestAndBranch(r0, true_label_, &discard); | 897 TestAndBranch(r0, true_label_, &discard); |
| 936 __ bind(&discard); | 898 __ bind(&discard); |
| 937 __ pop(); | 899 __ Drop(1); |
| 938 __ jmp(false_label_); | 900 __ jmp(false_label_); |
| 939 break; | 901 break; |
| 940 } | 902 } |
| 941 case Expression::kTestValue: { | 903 case Expression::kTestValue: { |
| 942 Label discard; | 904 Label discard; |
| 943 __ ldr(r0, MemOperand(sp)); | 905 __ ldr(r0, MemOperand(sp)); |
| 944 __ str(r0, target); | 906 __ str(r0, target); |
| 945 TestAndBranch(r0, &discard, false_label_); | 907 TestAndBranch(r0, &discard, false_label_); |
| 946 __ bind(&discard); | 908 __ bind(&discard); |
| 947 __ pop(); | 909 __ Drop(1); |
| 948 __ jmp(true_label_); | 910 __ jmp(true_label_); |
| 949 break; | 911 break; |
| 950 } | 912 } |
| 951 } | 913 } |
| 952 break; | 914 break; |
| 953 } | 915 } |
| 954 | 916 |
| 955 case Slot::CONTEXT: { | 917 case Slot::CONTEXT: { |
| 956 MemOperand target = EmitSlotSearch(slot, r1); | 918 MemOperand target = EmitSlotSearch(slot, r1); |
| 957 __ pop(r0); | 919 __ pop(r0); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 969 // register. Skip the write barrier if the value written (r1) is a smi. | 931 // register. Skip the write barrier if the value written (r1) is a smi. |
| 970 // The smi test is part of RecordWrite on other platforms, not on arm. | 932 // The smi test is part of RecordWrite on other platforms, not on arm. |
| 971 Label exit; | 933 Label exit; |
| 972 __ tst(r0, Operand(kSmiTagMask)); | 934 __ tst(r0, Operand(kSmiTagMask)); |
| 973 __ b(eq, &exit); | 935 __ b(eq, &exit); |
| 974 | 936 |
| 975 __ mov(r2, Operand(offset)); | 937 __ mov(r2, Operand(offset)); |
| 976 __ RecordWrite(r1, r2, r0); | 938 __ RecordWrite(r1, r2, r0); |
| 977 __ bind(&exit); | 939 __ bind(&exit); |
| 978 if (context != Expression::kEffect && context != Expression::kValue) { | 940 if (context != Expression::kEffect && context != Expression::kValue) { |
| 979 Move(context, r3); | 941 Apply(context, r3); |
| 980 } | 942 } |
| 981 break; | 943 break; |
| 982 } | 944 } |
| 983 | 945 |
| 984 case Slot::LOOKUP: | 946 case Slot::LOOKUP: |
| 985 UNREACHABLE(); | 947 UNREACHABLE(); |
| 986 break; | 948 break; |
| 987 } | 949 } |
| 988 } else { | 950 } else { |
| 989 // Variables rewritten as properties are not treated as variables in | 951 // Variables rewritten as properties are not treated as variables in |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1015 | 977 |
| 1016 // If the assignment ends an initialization block, revert to fast case. | 978 // If the assignment ends an initialization block, revert to fast case. |
| 1017 if (expr->ends_initialization_block()) { | 979 if (expr->ends_initialization_block()) { |
| 1018 __ push(r0); // Result of assignment, saved even if not needed. | 980 __ push(r0); // Result of assignment, saved even if not needed. |
| 1019 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. | 981 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. |
| 1020 __ push(ip); | 982 __ push(ip); |
| 1021 __ CallRuntime(Runtime::kToFastProperties, 1); | 983 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1022 __ pop(r0); | 984 __ pop(r0); |
| 1023 } | 985 } |
| 1024 | 986 |
| 1025 DropAndMove(expr->context(), r0); | 987 DropAndApply(1, expr->context(), r0); |
| 1026 } | 988 } |
| 1027 | 989 |
| 1028 | 990 |
| 1029 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 991 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1030 // Assignment to a property, using a keyed store IC. | 992 // Assignment to a property, using a keyed store IC. |
| 1031 | 993 |
| 1032 // If the assignment starts a block of assignments to the same object, | 994 // If the assignment starts a block of assignments to the same object, |
| 1033 // change to slow case to avoid the quadratic behavior of repeatedly | 995 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1034 // adding fast properties. | 996 // adding fast properties. |
| 1035 if (expr->starts_initialization_block()) { | 997 if (expr->starts_initialization_block()) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1047 if (expr->ends_initialization_block()) { | 1009 if (expr->ends_initialization_block()) { |
| 1048 __ push(r0); // Result of assignment, saved even if not needed. | 1010 __ push(r0); // Result of assignment, saved even if not needed. |
| 1049 // Reciever is under the key and value. | 1011 // Reciever is under the key and value. |
| 1050 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); | 1012 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); |
| 1051 __ push(ip); | 1013 __ push(ip); |
| 1052 __ CallRuntime(Runtime::kToFastProperties, 1); | 1014 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1053 __ pop(r0); | 1015 __ pop(r0); |
| 1054 } | 1016 } |
| 1055 | 1017 |
| 1056 // Receiver and key are still on stack. | 1018 // Receiver and key are still on stack. |
| 1057 __ add(sp, sp, Operand(2 * kPointerSize)); | 1019 DropAndApply(2, expr->context(), r0); |
| 1058 Move(expr->context(), r0); | |
| 1059 } | 1020 } |
| 1060 | 1021 |
| 1061 | 1022 |
| 1062 void FastCodeGenerator::VisitProperty(Property* expr) { | 1023 void FastCodeGenerator::VisitProperty(Property* expr) { |
| 1063 Comment cmnt(masm_, "[ Property"); | 1024 Comment cmnt(masm_, "[ Property"); |
| 1064 Expression* key = expr->key(); | 1025 Expression* key = expr->key(); |
| 1065 uint32_t dummy; | |
| 1066 | 1026 |
| 1067 // Record the source position for the property load. | 1027 // Record the source position for the property load. |
| 1068 SetSourcePosition(expr->position()); | 1028 SetSourcePosition(expr->position()); |
| 1069 | 1029 |
| 1070 // Evaluate receiver. | 1030 // Evaluate receiver. |
| 1071 Visit(expr->obj()); | 1031 Visit(expr->obj()); |
| 1072 | 1032 |
| 1073 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && | 1033 if (key->IsPropertyName()) { |
| 1074 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { | 1034 // Do a named property load. The IC expects the property name in r2 and |
| 1075 // Do a NAMED property load. | 1035 // the receiver on the stack. |
| 1076 // The IC expects the property name in r2 and the receiver on the stack. | |
| 1077 __ mov(r2, Operand(key->AsLiteral()->handle())); | 1036 __ mov(r2, Operand(key->AsLiteral()->handle())); |
| 1078 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1037 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1079 __ Call(ic, RelocInfo::CODE_TARGET); | 1038 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1039 DropAndApply(1, expr->context(), r0); | |
| 1080 } else { | 1040 } else { |
| 1081 // Do a KEYED property load. | 1041 // Do a keyed property load. |
| 1082 Visit(expr->key()); | 1042 Visit(expr->key()); |
| 1083 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1043 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1084 __ Call(ic, RelocInfo::CODE_TARGET); | 1044 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1085 // Drop key and receiver left on the stack by IC. | 1045 // Drop key and receiver left on the stack by IC. |
| 1086 __ pop(); | 1046 DropAndApply(2, expr->context(), r0); |
| 1087 } | 1047 } |
| 1088 DropAndMove(expr->context(), r0); | |
| 1089 } | 1048 } |
| 1090 | 1049 |
| 1091 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1050 void FastCodeGenerator::EmitCallWithIC(Call* expr, |
| 1092 Handle<Object> ignored, | 1051 Handle<Object> ignored, |
| 1093 RelocInfo::Mode mode) { | 1052 RelocInfo::Mode mode) { |
| 1094 // Code common for calls using the IC. | 1053 // Code common for calls using the IC. |
| 1095 ZoneList<Expression*>* args = expr->arguments(); | 1054 ZoneList<Expression*>* args = expr->arguments(); |
| 1096 int arg_count = args->length(); | 1055 int arg_count = args->length(); |
| 1097 for (int i = 0; i < arg_count; i++) { | 1056 for (int i = 0; i < arg_count; i++) { |
| 1098 Visit(args->at(i)); | 1057 Visit(args->at(i)); |
| 1099 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 1058 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
| 1100 } | 1059 } |
| 1101 // Record source position for debugger. | 1060 // Record source position for debugger. |
| 1102 SetSourcePosition(expr->position()); | 1061 SetSourcePosition(expr->position()); |
| 1103 // Call the IC initialization code. | 1062 // Call the IC initialization code. |
| 1104 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1063 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 1105 NOT_IN_LOOP); | 1064 NOT_IN_LOOP); |
| 1106 __ Call(ic, mode); | 1065 __ Call(ic, mode); |
| 1107 // Restore context register. | 1066 // Restore context register. |
| 1108 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1067 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1109 // Discard the function left on TOS. | 1068 // Discard the function left on TOS. |
| 1110 DropAndMove(expr->context(), r0); | 1069 DropAndApply(1, expr->context(), r0); |
| 1111 } | 1070 } |
| 1112 | 1071 |
| 1113 | 1072 |
| 1114 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1073 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
| 1115 // Code common for calls using the call stub. | 1074 // Code common for calls using the call stub. |
| 1116 ZoneList<Expression*>* args = expr->arguments(); | 1075 ZoneList<Expression*>* args = expr->arguments(); |
| 1117 int arg_count = args->length(); | 1076 int arg_count = args->length(); |
| 1118 for (int i = 0; i < arg_count; i++) { | 1077 for (int i = 0; i < arg_count; i++) { |
| 1119 Visit(args->at(i)); | 1078 Visit(args->at(i)); |
| 1120 } | 1079 } |
| 1121 // Record source position for debugger. | 1080 // Record source position for debugger. |
| 1122 SetSourcePosition(expr->position()); | 1081 SetSourcePosition(expr->position()); |
| 1123 CallFunctionStub stub(arg_count, NOT_IN_LOOP); | 1082 CallFunctionStub stub(arg_count, NOT_IN_LOOP); |
| 1124 __ CallStub(&stub); | 1083 __ CallStub(&stub); |
| 1125 // Restore context register. | 1084 // Restore context register. |
| 1126 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1085 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1127 // Discard the function left on TOS. | 1086 // Discard the function left on TOS. |
| 1128 DropAndMove(expr->context(), r0); | 1087 DropAndApply(1, expr->context(), r0); |
| 1129 } | 1088 } |
| 1130 | 1089 |
| 1131 | 1090 |
| 1132 void FastCodeGenerator::VisitCall(Call* expr) { | 1091 void FastCodeGenerator::VisitCall(Call* expr) { |
| 1133 Comment cmnt(masm_, "[ Call"); | 1092 Comment cmnt(masm_, "[ Call"); |
| 1134 Expression* fun = expr->expression(); | 1093 Expression* fun = expr->expression(); |
| 1135 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1094 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 1136 | 1095 |
| 1137 if (var != NULL && var->is_possibly_eval()) { | 1096 if (var != NULL && var->is_possibly_eval()) { |
| 1138 // Call to the identifier 'eval'. | 1097 // Call to the identifier 'eval'. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1227 | 1186 |
| 1228 // Load function, arg_count into r1 and r0. | 1187 // Load function, arg_count into r1 and r0. |
| 1229 __ mov(r0, Operand(arg_count)); | 1188 __ mov(r0, Operand(arg_count)); |
| 1230 // Function is in sp[arg_count + 1]. | 1189 // Function is in sp[arg_count + 1]. |
| 1231 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 1190 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 1232 | 1191 |
| 1233 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1192 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
| 1234 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1193 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
| 1235 | 1194 |
| 1236 // Replace function on TOS with result in r0, or pop it. | 1195 // Replace function on TOS with result in r0, or pop it. |
| 1237 DropAndMove(expr->context(), r0); | 1196 DropAndApply(1, expr->context(), r0); |
| 1238 } | 1197 } |
| 1239 | 1198 |
| 1240 | 1199 |
| 1241 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1200 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 1242 Comment cmnt(masm_, "[ CallRuntime"); | 1201 Comment cmnt(masm_, "[ CallRuntime"); |
| 1243 ZoneList<Expression*>* args = expr->arguments(); | 1202 ZoneList<Expression*>* args = expr->arguments(); |
| 1244 | 1203 |
| 1245 if (expr->is_jsruntime()) { | 1204 if (expr->is_jsruntime()) { |
| 1246 // Prepare for calling JS runtime function. | 1205 // Prepare for calling JS runtime function. |
| 1247 __ mov(r1, Operand(expr->name())); | 1206 __ mov(r1, Operand(expr->name())); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1258 } | 1217 } |
| 1259 | 1218 |
| 1260 if (expr->is_jsruntime()) { | 1219 if (expr->is_jsruntime()) { |
| 1261 // Call the JS runtime function. | 1220 // Call the JS runtime function. |
| 1262 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1221 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 1263 NOT_IN_LOOP); | 1222 NOT_IN_LOOP); |
| 1264 __ Call(ic, RelocInfo::CODE_TARGET); | 1223 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1265 // Restore context register. | 1224 // Restore context register. |
| 1266 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1225 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1267 // Discard the function left on TOS. | 1226 // Discard the function left on TOS. |
| 1268 DropAndMove(expr->context(), r0); | 1227 DropAndApply(1, expr->context(), r0); |
| 1269 } else { | 1228 } else { |
| 1270 // Call the C runtime function. | 1229 // Call the C runtime function. |
| 1271 __ CallRuntime(expr->function(), arg_count); | 1230 __ CallRuntime(expr->function(), arg_count); |
| 1272 Move(expr->context(), r0); | 1231 Apply(expr->context(), r0); |
| 1273 } | 1232 } |
| 1274 } | 1233 } |
| 1275 | 1234 |
| 1276 | 1235 |
| 1277 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1236 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 1278 switch (expr->op()) { | 1237 switch (expr->op()) { |
| 1279 case Token::VOID: { | 1238 case Token::VOID: { |
| 1280 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1239 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
| 1281 Visit(expr->expression()); | 1240 Visit(expr->expression()); |
| 1282 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1241 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1391 __ mov(r0, Operand(proxy->name())); | 1350 __ mov(r0, Operand(proxy->name())); |
| 1392 __ stm(db_w, sp, cp.bit() | r0.bit()); | 1351 __ stm(db_w, sp, cp.bit() | r0.bit()); |
| 1393 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1352 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 1394 __ push(r0); | 1353 __ push(r0); |
| 1395 } else { | 1354 } else { |
| 1396 // This expression cannot throw a reference error at the top level. | 1355 // This expression cannot throw a reference error at the top level. |
| 1397 Visit(expr->expression()); | 1356 Visit(expr->expression()); |
| 1398 } | 1357 } |
| 1399 | 1358 |
| 1400 __ CallRuntime(Runtime::kTypeof, 1); | 1359 __ CallRuntime(Runtime::kTypeof, 1); |
| 1401 Move(expr->context(), r0); | 1360 Apply(expr->context(), r0); |
| 1402 break; | 1361 break; |
| 1403 } | 1362 } |
| 1404 | 1363 |
| 1405 default: | 1364 default: |
| 1406 UNREACHABLE(); | 1365 UNREACHABLE(); |
| 1407 } | 1366 } |
| 1408 } | 1367 } |
| 1409 | 1368 |
| 1410 | 1369 |
| 1411 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1370 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1492 // Store the value returned in r0. | 1451 // Store the value returned in r0. |
| 1493 switch (assign_type) { | 1452 switch (assign_type) { |
| 1494 case VARIABLE: | 1453 case VARIABLE: |
| 1495 __ push(r0); | 1454 __ push(r0); |
| 1496 if (expr->is_postfix()) { | 1455 if (expr->is_postfix()) { |
| 1497 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1456 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1498 Expression::kEffect); | 1457 Expression::kEffect); |
| 1499 // For all contexts except kEffect: We have the result on | 1458 // For all contexts except kEffect: We have the result on |
| 1500 // top of the stack. | 1459 // top of the stack. |
| 1501 if (expr->context() != Expression::kEffect) { | 1460 if (expr->context() != Expression::kEffect) { |
| 1502 MoveTOS(expr->context()); | 1461 ApplyTOS(expr->context()); |
| 1503 } | 1462 } |
| 1504 } else { | 1463 } else { |
| 1505 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1464 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1506 expr->context()); | 1465 expr->context()); |
| 1507 } | 1466 } |
| 1508 break; | 1467 break; |
| 1509 case NAMED_PROPERTY: { | 1468 case NAMED_PROPERTY: { |
| 1510 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1469 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
| 1511 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1470 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1512 __ Call(ic, RelocInfo::CODE_TARGET); | 1471 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1513 if (expr->is_postfix()) { | 1472 if (expr->is_postfix()) { |
| 1514 __ Drop(1); // Result is on the stack under the receiver. | 1473 __ Drop(1); // Result is on the stack under the receiver. |
| 1515 if (expr->context() != Expression::kEffect) { | 1474 if (expr->context() != Expression::kEffect) { |
| 1516 MoveTOS(expr->context()); | 1475 ApplyTOS(expr->context()); |
| 1517 } | 1476 } |
| 1518 } else { | 1477 } else { |
| 1519 DropAndMove(expr->context(), r0); | 1478 DropAndApply(1, expr->context(), r0); |
| 1520 } | 1479 } |
| 1521 break; | 1480 break; |
| 1522 } | 1481 } |
| 1523 case KEYED_PROPERTY: { | 1482 case KEYED_PROPERTY: { |
| 1524 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1483 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1525 __ Call(ic, RelocInfo::CODE_TARGET); | 1484 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1526 if (expr->is_postfix()) { | 1485 if (expr->is_postfix()) { |
| 1527 __ Drop(2); // Result is on the stack under the key and the receiver. | 1486 __ Drop(2); // Result is on the stack under the key and the receiver. |
| 1528 if (expr->context() != Expression::kEffect) { | 1487 if (expr->context() != Expression::kEffect) { |
| 1529 MoveTOS(expr->context()); | 1488 ApplyTOS(expr->context()); |
| 1530 } | 1489 } |
| 1531 } else { | 1490 } else { |
| 1532 DropAndMove(expr->context(), r0, 2); | 1491 DropAndApply(2, expr->context(), r0); |
| 1533 } | 1492 } |
| 1534 break; | 1493 break; |
| 1535 } | 1494 } |
| 1536 } | 1495 } |
| 1537 } | 1496 } |
| 1538 | 1497 |
| 1539 | 1498 |
| 1540 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1499 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 1541 Comment cmnt(masm_, "[ BinaryOperation"); | 1500 Comment cmnt(masm_, "[ BinaryOperation"); |
| 1542 switch (expr->op()) { | 1501 switch (expr->op()) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1566 ASSERT_EQ(Expression::kValue, expr->left()->context()); | 1525 ASSERT_EQ(Expression::kValue, expr->left()->context()); |
| 1567 ASSERT_EQ(Expression::kValue, expr->right()->context()); | 1526 ASSERT_EQ(Expression::kValue, expr->right()->context()); |
| 1568 | 1527 |
| 1569 Visit(expr->left()); | 1528 Visit(expr->left()); |
| 1570 Visit(expr->right()); | 1529 Visit(expr->right()); |
| 1571 __ pop(r0); | 1530 __ pop(r0); |
| 1572 __ pop(r1); | 1531 __ pop(r1); |
| 1573 GenericBinaryOpStub stub(expr->op(), | 1532 GenericBinaryOpStub stub(expr->op(), |
| 1574 NO_OVERWRITE); | 1533 NO_OVERWRITE); |
| 1575 __ CallStub(&stub); | 1534 __ CallStub(&stub); |
| 1576 Move(expr->context(), r0); | 1535 Apply(expr->context(), r0); |
| 1577 | 1536 |
| 1578 break; | 1537 break; |
| 1579 } | 1538 } |
| 1580 default: | 1539 default: |
| 1581 UNREACHABLE(); | 1540 UNREACHABLE(); |
| 1582 } | 1541 } |
| 1583 } | 1542 } |
| 1584 | 1543 |
| 1585 | 1544 |
| 1586 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1545 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1741 break; | 1700 break; |
| 1742 } | 1701 } |
| 1743 true_label_ = saved_true; | 1702 true_label_ = saved_true; |
| 1744 false_label_ = saved_false; | 1703 false_label_ = saved_false; |
| 1745 // Convert current context to test context: End post-test code. | 1704 // Convert current context to test context: End post-test code. |
| 1746 } | 1705 } |
| 1747 | 1706 |
| 1748 | 1707 |
| 1749 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1708 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 1750 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1709 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1751 Move(expr->context(), r0); | 1710 Apply(expr->context(), r0); |
| 1752 } | 1711 } |
| 1753 | 1712 |
| 1754 | 1713 |
| 1755 Register FastCodeGenerator::result_register() { return r0; } | 1714 Register FastCodeGenerator::result_register() { return r0; } |
| 1756 | 1715 |
| 1757 | 1716 |
| 1758 Register FastCodeGenerator::context_register() { return cp; } | 1717 Register FastCodeGenerator::context_register() { return cp; } |
| 1759 | 1718 |
| 1760 | 1719 |
| 1761 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1720 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1793 __ pop(result_register()); | 1752 __ pop(result_register()); |
| 1794 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1753 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
| 1795 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 1754 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 1796 __ add(pc, r1, Operand(masm_->CodeObject())); | 1755 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 1797 } | 1756 } |
| 1798 | 1757 |
| 1799 | 1758 |
| 1800 #undef __ | 1759 #undef __ |
| 1801 | 1760 |
| 1802 } } // namespace v8::internal | 1761 } } // namespace v8::internal |
| OLD | NEW |