| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 } | 163 } |
| 164 // Visit all the explicit declarations unless there is an illegal | 164 // Visit all the explicit declarations unless there is an illegal |
| 165 // redeclaration. | 165 // redeclaration. |
| 166 if (scope()->HasIllegalRedeclaration()) { | 166 if (scope()->HasIllegalRedeclaration()) { |
| 167 scope()->VisitIllegalRedeclaration(this); | 167 scope()->VisitIllegalRedeclaration(this); |
| 168 } else { | 168 } else { |
| 169 VisitDeclarations(scope()->declarations()); | 169 VisitDeclarations(scope()->declarations()); |
| 170 } | 170 } |
| 171 } | 171 } |
| 172 | 172 |
| 173 if (FLAG_trace) { |
| 174 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 175 } |
| 176 |
| 173 { Comment cmnt(masm_, "[ Stack check"); | 177 { Comment cmnt(masm_, "[ Stack check"); |
| 178 PrepareForBailout(info->function(), NO_REGISTERS); |
| 174 NearLabel ok; | 179 NearLabel ok; |
| 175 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 180 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
| 176 __ j(above_equal, &ok); | 181 __ j(above_equal, &ok); |
| 177 StackCheckStub stub; | 182 StackCheckStub stub; |
| 178 __ CallStub(&stub); | 183 __ CallStub(&stub); |
| 179 __ bind(&ok); | 184 __ bind(&ok); |
| 180 } | 185 } |
| 181 | 186 |
| 182 if (FLAG_trace) { | |
| 183 __ CallRuntime(Runtime::kTraceEnter, 0); | |
| 184 } | |
| 185 | |
| 186 { Comment cmnt(masm_, "[ Body"); | 187 { Comment cmnt(masm_, "[ Body"); |
| 187 ASSERT(loop_depth() == 0); | 188 ASSERT(loop_depth() == 0); |
| 188 VisitStatements(function()->body()); | 189 VisitStatements(function()->body()); |
| 189 ASSERT(loop_depth() == 0); | 190 ASSERT(loop_depth() == 0); |
| 190 } | 191 } |
| 191 | 192 |
| 192 { Comment cmnt(masm_, "[ return <undefined>;"); | 193 { Comment cmnt(masm_, "[ return <undefined>;"); |
| 193 // Emit a 'return undefined' in case control fell off the end of the body. | 194 // Emit a 'return undefined' in case control fell off the end of the body. |
| 194 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 195 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 195 EmitReturnSequence(); | 196 EmitReturnSequence(); |
| 196 } | 197 } |
| 197 } | 198 } |
| 198 | 199 |
| 199 | 200 |
| 201 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { |
| 202 Comment cmnt(masm_, "[ Stack check"); |
| 203 NearLabel ok; |
| 204 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
| 205 __ j(above_equal, &ok); |
| 206 StackCheckStub stub; |
| 207 __ CallStub(&stub); |
| 208 __ bind(&ok); |
| 209 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 210 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); |
| 211 RecordStackCheck(stmt->OsrEntryId()); |
| 212 } |
| 213 |
| 214 |
| 200 void FullCodeGenerator::EmitReturnSequence() { | 215 void FullCodeGenerator::EmitReturnSequence() { |
| 201 Comment cmnt(masm_, "[ Return sequence"); | 216 Comment cmnt(masm_, "[ Return sequence"); |
| 202 if (return_label_.is_bound()) { | 217 if (return_label_.is_bound()) { |
| 203 __ jmp(&return_label_); | 218 __ jmp(&return_label_); |
| 204 } else { | 219 } else { |
| 205 __ bind(&return_label_); | 220 __ bind(&return_label_); |
| 206 if (FLAG_trace) { | 221 if (FLAG_trace) { |
| 207 __ push(rax); | 222 __ push(rax); |
| 208 __ CallRuntime(Runtime::kTraceExit, 1); | 223 __ CallRuntime(Runtime::kTraceExit, 1); |
| 209 } | 224 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 | 269 |
| 255 | 270 |
| 256 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { | 271 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { |
| 257 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); | 272 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); |
| 258 __ push(slot_operand); | 273 __ push(slot_operand); |
| 259 } | 274 } |
| 260 | 275 |
| 261 | 276 |
| 262 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { | 277 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { |
| 263 codegen()->Move(result_register(), slot); | 278 codegen()->Move(result_register(), slot); |
| 279 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 264 codegen()->DoTest(true_label_, false_label_, fall_through_); | 280 codegen()->DoTest(true_label_, false_label_, fall_through_); |
| 265 } | 281 } |
| 266 | 282 |
| 267 | 283 |
| 268 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 284 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
| 269 } | 285 } |
| 270 | 286 |
| 271 | 287 |
| 272 void FullCodeGenerator::AccumulatorValueContext::Plug( | 288 void FullCodeGenerator::AccumulatorValueContext::Plug( |
| 273 Heap::RootListIndex index) const { | 289 Heap::RootListIndex index) const { |
| 274 __ LoadRoot(result_register(), index); | 290 __ LoadRoot(result_register(), index); |
| 275 } | 291 } |
| 276 | 292 |
| 277 | 293 |
| 278 void FullCodeGenerator::StackValueContext::Plug( | 294 void FullCodeGenerator::StackValueContext::Plug( |
| 279 Heap::RootListIndex index) const { | 295 Heap::RootListIndex index) const { |
| 280 __ PushRoot(index); | 296 __ PushRoot(index); |
| 281 } | 297 } |
| 282 | 298 |
| 283 | 299 |
| 284 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { | 300 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { |
| 301 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, |
| 302 true, |
| 303 true_label_, |
| 304 false_label_); |
| 285 if (index == Heap::kUndefinedValueRootIndex || | 305 if (index == Heap::kUndefinedValueRootIndex || |
| 286 index == Heap::kNullValueRootIndex || | 306 index == Heap::kNullValueRootIndex || |
| 287 index == Heap::kFalseValueRootIndex) { | 307 index == Heap::kFalseValueRootIndex) { |
| 288 __ jmp(false_label_); | 308 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 289 } else if (index == Heap::kTrueValueRootIndex) { | 309 } else if (index == Heap::kTrueValueRootIndex) { |
| 290 __ jmp(true_label_); | 310 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 291 } else { | 311 } else { |
| 292 __ LoadRoot(result_register(), index); | 312 __ LoadRoot(result_register(), index); |
| 293 codegen()->DoTest(true_label_, false_label_, fall_through_); | 313 codegen()->DoTest(true_label_, false_label_, fall_through_); |
| 294 } | 314 } |
| 295 } | 315 } |
| 296 | 316 |
| 297 | 317 |
| 298 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { | 318 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { |
| 299 } | 319 } |
| 300 | 320 |
| 301 | 321 |
| 302 void FullCodeGenerator::AccumulatorValueContext::Plug( | 322 void FullCodeGenerator::AccumulatorValueContext::Plug( |
| 303 Handle<Object> lit) const { | 323 Handle<Object> lit) const { |
| 304 __ Move(result_register(), lit); | 324 __ Move(result_register(), lit); |
| 305 } | 325 } |
| 306 | 326 |
| 307 | 327 |
| 308 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { | 328 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
| 309 __ Push(lit); | 329 __ Push(lit); |
| 310 } | 330 } |
| 311 | 331 |
| 312 | 332 |
| 313 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 333 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
| 334 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, |
| 335 true, |
| 336 true_label_, |
| 337 false_label_); |
| 314 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 338 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. |
| 315 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 339 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
| 316 __ jmp(false_label_); | 340 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 317 } else if (lit->IsTrue() || lit->IsJSObject()) { | 341 } else if (lit->IsTrue() || lit->IsJSObject()) { |
| 318 __ jmp(true_label_); | 342 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 319 } else if (lit->IsString()) { | 343 } else if (lit->IsString()) { |
| 320 if (String::cast(*lit)->length() == 0) { | 344 if (String::cast(*lit)->length() == 0) { |
| 321 __ jmp(false_label_); | 345 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 322 } else { | 346 } else { |
| 323 __ jmp(true_label_); | 347 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 324 } | 348 } |
| 325 } else if (lit->IsSmi()) { | 349 } else if (lit->IsSmi()) { |
| 326 if (Smi::cast(*lit)->value() == 0) { | 350 if (Smi::cast(*lit)->value() == 0) { |
| 327 __ jmp(false_label_); | 351 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 328 } else { | 352 } else { |
| 329 __ jmp(true_label_); | 353 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 330 } | 354 } |
| 331 } else { | 355 } else { |
| 332 // For simplicity we always test the accumulator register. | 356 // For simplicity we always test the accumulator register. |
| 333 __ Move(result_register(), lit); | 357 __ Move(result_register(), lit); |
| 334 codegen()->DoTest(true_label_, false_label_, fall_through_); | 358 codegen()->DoTest(true_label_, false_label_, fall_through_); |
| 335 } | 359 } |
| 336 } | 360 } |
| 337 | 361 |
| 338 | 362 |
| 339 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 363 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 359 __ movq(Operand(rsp, 0), reg); | 383 __ movq(Operand(rsp, 0), reg); |
| 360 } | 384 } |
| 361 | 385 |
| 362 | 386 |
| 363 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 387 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
| 364 Register reg) const { | 388 Register reg) const { |
| 365 ASSERT(count > 0); | 389 ASSERT(count > 0); |
| 366 // For simplicity we always test the accumulator register. | 390 // For simplicity we always test the accumulator register. |
| 367 __ Drop(count); | 391 __ Drop(count); |
| 368 __ Move(result_register(), reg); | 392 __ Move(result_register(), reg); |
| 393 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 369 codegen()->DoTest(true_label_, false_label_, fall_through_); | 394 codegen()->DoTest(true_label_, false_label_, fall_through_); |
| 370 } | 395 } |
| 371 | 396 |
| 372 | 397 |
| 373 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 398 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
| 374 Label* materialize_false) const { | 399 Label* materialize_false) const { |
| 375 ASSERT_EQ(materialize_true, materialize_false); | 400 ASSERT(materialize_true == materialize_false); |
| 376 __ bind(materialize_true); | 401 __ bind(materialize_true); |
| 377 } | 402 } |
| 378 | 403 |
| 379 | 404 |
| 380 void FullCodeGenerator::AccumulatorValueContext::Plug( | 405 void FullCodeGenerator::AccumulatorValueContext::Plug( |
| 381 Label* materialize_true, | 406 Label* materialize_true, |
| 382 Label* materialize_false) const { | 407 Label* materialize_false) const { |
| 383 NearLabel done; | 408 NearLabel done; |
| 384 __ bind(materialize_true); | 409 __ bind(materialize_true); |
| 385 __ Move(result_register(), FACTORY->true_value()); | 410 __ Move(result_register(), FACTORY->true_value()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 398 __ Push(FACTORY->true_value()); | 423 __ Push(FACTORY->true_value()); |
| 399 __ jmp(&done); | 424 __ jmp(&done); |
| 400 __ bind(materialize_false); | 425 __ bind(materialize_false); |
| 401 __ Push(FACTORY->false_value()); | 426 __ Push(FACTORY->false_value()); |
| 402 __ bind(&done); | 427 __ bind(&done); |
| 403 } | 428 } |
| 404 | 429 |
| 405 | 430 |
| 406 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 431 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
| 407 Label* materialize_false) const { | 432 Label* materialize_false) const { |
| 433 ASSERT(materialize_true == true_label_); |
| 408 ASSERT(materialize_false == false_label_); | 434 ASSERT(materialize_false == false_label_); |
| 409 ASSERT(materialize_true == true_label_); | |
| 410 } | 435 } |
| 411 | 436 |
| 412 | 437 |
| 413 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 438 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
| 414 } | 439 } |
| 415 | 440 |
| 416 | 441 |
| 417 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 442 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
| 418 Heap::RootListIndex value_root_index = | 443 Heap::RootListIndex value_root_index = |
| 419 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 444 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
| 420 __ LoadRoot(result_register(), value_root_index); | 445 __ LoadRoot(result_register(), value_root_index); |
| 421 } | 446 } |
| 422 | 447 |
| 423 | 448 |
| 424 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 449 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
| 425 Heap::RootListIndex value_root_index = | 450 Heap::RootListIndex value_root_index = |
| 426 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 451 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
| 427 __ PushRoot(value_root_index); | 452 __ PushRoot(value_root_index); |
| 428 } | 453 } |
| 429 | 454 |
| 430 | 455 |
| 431 void FullCodeGenerator::TestContext::Plug(bool flag) const { | 456 void FullCodeGenerator::TestContext::Plug(bool flag) const { |
| 457 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| 432 if (flag) { | 458 if (flag) { |
| 433 if (true_label_ != fall_through_) __ jmp(true_label_); | 459 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 434 } else { | 460 } else { |
| 435 if (false_label_ != fall_through_) __ jmp(false_label_); | 461 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 436 } | 462 } |
| 437 } | 463 } |
| 438 | 464 |
| 439 | 465 |
| 440 void FullCodeGenerator::DoTest(Label* if_true, | 466 void FullCodeGenerator::DoTest(Label* if_true, |
| 441 Label* if_false, | 467 Label* if_false, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 MemOperand location = EmitSlotSearch(dst, scratch1); | 539 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 514 __ movq(location, src); | 540 __ movq(location, src); |
| 515 // Emit the write barrier code if the location is in the heap. | 541 // Emit the write barrier code if the location is in the heap. |
| 516 if (dst->type() == Slot::CONTEXT) { | 542 if (dst->type() == Slot::CONTEXT) { |
| 517 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | 543 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
| 518 __ RecordWrite(scratch1, offset, src, scratch2); | 544 __ RecordWrite(scratch1, offset, src, scratch2); |
| 519 } | 545 } |
| 520 } | 546 } |
| 521 | 547 |
| 522 | 548 |
| 549 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, |
| 550 bool should_normalize, |
| 551 Label* if_true, |
| 552 Label* if_false) { |
| 553 } |
| 554 |
| 555 |
| 523 void FullCodeGenerator::EmitDeclaration(Variable* variable, | 556 void FullCodeGenerator::EmitDeclaration(Variable* variable, |
| 524 Variable::Mode mode, | 557 Variable::Mode mode, |
| 525 FunctionLiteral* function) { | 558 FunctionLiteral* function) { |
| 526 Comment cmnt(masm_, "[ Declaration"); | 559 Comment cmnt(masm_, "[ Declaration"); |
| 527 ASSERT(variable != NULL); // Must have been resolved. | 560 ASSERT(variable != NULL); // Must have been resolved. |
| 528 Slot* slot = variable->AsSlot(); | 561 Slot* slot = variable->AsSlot(); |
| 529 Property* prop = variable->AsProperty(); | 562 Property* prop = variable->AsProperty(); |
| 530 | 563 |
| 531 if (slot != NULL) { | 564 if (slot != NULL) { |
| 532 switch (slot->type()) { | 565 switch (slot->type()) { |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 __ movq(rbx, rax); | 836 __ movq(rbx, rax); |
| 804 | 837 |
| 805 // Update the 'each' property or variable from the possibly filtered | 838 // Update the 'each' property or variable from the possibly filtered |
| 806 // entry in register rbx. | 839 // entry in register rbx. |
| 807 __ bind(&update_each); | 840 __ bind(&update_each); |
| 808 __ movq(result_register(), rbx); | 841 __ movq(result_register(), rbx); |
| 809 // Perform the assignment as if via '='. | 842 // Perform the assignment as if via '='. |
| 810 EmitAssignment(stmt->each()); | 843 EmitAssignment(stmt->each()); |
| 811 | 844 |
| 812 // Generate code for the body of the loop. | 845 // Generate code for the body of the loop. |
| 813 Label stack_limit_hit, stack_check_done; | |
| 814 Visit(stmt->body()); | 846 Visit(stmt->body()); |
| 815 | 847 |
| 816 __ StackLimitCheck(&stack_limit_hit); | |
| 817 __ bind(&stack_check_done); | |
| 818 | |
| 819 // Generate code for going to the next element by incrementing the | 848 // Generate code for going to the next element by incrementing the |
| 820 // index (smi) stored on top of the stack. | 849 // index (smi) stored on top of the stack. |
| 821 __ bind(loop_statement.continue_target()); | 850 __ bind(loop_statement.continue_target()); |
| 822 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); | 851 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); |
| 852 |
| 853 EmitStackCheck(stmt); |
| 823 __ jmp(&loop); | 854 __ jmp(&loop); |
| 824 | 855 |
| 825 // Slow case for the stack limit check. | |
| 826 StackCheckStub stack_check_stub; | |
| 827 __ bind(&stack_limit_hit); | |
| 828 __ CallStub(&stack_check_stub); | |
| 829 __ jmp(&stack_check_done); | |
| 830 | |
| 831 // Remove the pointers stored on the stack. | 856 // Remove the pointers stored on the stack. |
| 832 __ bind(loop_statement.break_target()); | 857 __ bind(loop_statement.break_target()); |
| 833 __ addq(rsp, Immediate(5 * kPointerSize)); | 858 __ addq(rsp, Immediate(5 * kPointerSize)); |
| 834 | 859 |
| 835 // Exit and decrement the loop depth. | 860 // Exit and decrement the loop depth. |
| 836 __ bind(&exit); | 861 __ bind(&exit); |
| 837 decrement_loop_depth(); | 862 decrement_loop_depth(); |
| 838 } | 863 } |
| 839 | 864 |
| 840 | 865 |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1712 } | 1737 } |
| 1713 | 1738 |
| 1714 | 1739 |
| 1715 void FullCodeGenerator::VisitProperty(Property* expr) { | 1740 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 1716 Comment cmnt(masm_, "[ Property"); | 1741 Comment cmnt(masm_, "[ Property"); |
| 1717 Expression* key = expr->key(); | 1742 Expression* key = expr->key(); |
| 1718 | 1743 |
| 1719 if (key->IsPropertyName()) { | 1744 if (key->IsPropertyName()) { |
| 1720 VisitForAccumulatorValue(expr->obj()); | 1745 VisitForAccumulatorValue(expr->obj()); |
| 1721 EmitNamedPropertyLoad(expr); | 1746 EmitNamedPropertyLoad(expr); |
| 1747 context()->Plug(rax); |
| 1722 } else { | 1748 } else { |
| 1723 VisitForStackValue(expr->obj()); | 1749 VisitForStackValue(expr->obj()); |
| 1724 VisitForAccumulatorValue(expr->key()); | 1750 VisitForAccumulatorValue(expr->key()); |
| 1725 __ pop(rdx); | 1751 __ pop(rdx); |
| 1726 EmitKeyedPropertyLoad(expr); | 1752 EmitKeyedPropertyLoad(expr); |
| 1753 context()->Plug(rax); |
| 1727 } | 1754 } |
| 1728 context()->Plug(rax); | |
| 1729 } | 1755 } |
| 1730 | 1756 |
| 1731 | 1757 |
| 1732 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 1758 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 1733 Handle<Object> name, | 1759 Handle<Object> name, |
| 1734 RelocInfo::Mode mode) { | 1760 RelocInfo::Mode mode) { |
| 1735 // Code common for calls using the IC. | 1761 // Code common for calls using the IC. |
| 1736 ZoneList<Expression*>* args = expr->arguments(); | 1762 ZoneList<Expression*>* args = expr->arguments(); |
| 1737 int arg_count = args->length(); | 1763 int arg_count = args->length(); |
| 1738 { PreservePositionScope scope(masm()->positions_recorder()); | 1764 { PreservePositionScope scope(masm()->positions_recorder()); |
| (...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2672 // InvokeFunction requires function in rdi. Move it in there. | 2698 // InvokeFunction requires function in rdi. Move it in there. |
| 2673 if (!result_register().is(rdi)) __ movq(rdi, result_register()); | 2699 if (!result_register().is(rdi)) __ movq(rdi, result_register()); |
| 2674 ParameterCount count(arg_count); | 2700 ParameterCount count(arg_count); |
| 2675 __ InvokeFunction(rdi, count, CALL_FUNCTION); | 2701 __ InvokeFunction(rdi, count, CALL_FUNCTION); |
| 2676 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2702 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2677 context()->Plug(rax); | 2703 context()->Plug(rax); |
| 2678 } | 2704 } |
| 2679 | 2705 |
| 2680 | 2706 |
| 2681 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { | 2707 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { |
| 2708 RegExpConstructResultStub stub; |
| 2682 ASSERT(args->length() == 3); | 2709 ASSERT(args->length() == 3); |
| 2683 VisitForStackValue(args->at(0)); | 2710 VisitForStackValue(args->at(0)); |
| 2684 VisitForStackValue(args->at(1)); | 2711 VisitForStackValue(args->at(1)); |
| 2685 VisitForStackValue(args->at(2)); | 2712 VisitForStackValue(args->at(2)); |
| 2686 __ CallRuntime(Runtime::kRegExpConstructResult, 3); | 2713 __ CallStub(&stub); |
| 2687 context()->Plug(rax); | 2714 context()->Plug(rax); |
| 2688 } | 2715 } |
| 2689 | 2716 |
| 2690 | 2717 |
| 2691 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { | 2718 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { |
| 2692 ASSERT(args->length() == 3); | 2719 ASSERT(args->length() == 3); |
| 2693 VisitForStackValue(args->at(0)); | 2720 VisitForStackValue(args->at(0)); |
| 2694 VisitForStackValue(args->at(1)); | 2721 VisitForStackValue(args->at(1)); |
| 2695 VisitForStackValue(args->at(2)); | 2722 VisitForStackValue(args->at(2)); |
| 2696 __ CallRuntime(Runtime::kSwapElements, 3); | 2723 __ CallRuntime(Runtime::kSwapElements, 3); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2939 VisitForTypeofValue(expr->expression()); | 2966 VisitForTypeofValue(expr->expression()); |
| 2940 } | 2967 } |
| 2941 __ CallRuntime(Runtime::kTypeof, 1); | 2968 __ CallRuntime(Runtime::kTypeof, 1); |
| 2942 context()->Plug(rax); | 2969 context()->Plug(rax); |
| 2943 break; | 2970 break; |
| 2944 } | 2971 } |
| 2945 | 2972 |
| 2946 case Token::ADD: { | 2973 case Token::ADD: { |
| 2947 Comment cmt(masm_, "[ UnaryOperation (ADD)"); | 2974 Comment cmt(masm_, "[ UnaryOperation (ADD)"); |
| 2948 VisitForAccumulatorValue(expr->expression()); | 2975 VisitForAccumulatorValue(expr->expression()); |
| 2949 NearLabel no_conversion; | 2976 Label no_conversion; |
| 2950 Condition is_smi = masm_->CheckSmi(result_register()); | 2977 Condition is_smi = masm_->CheckSmi(result_register()); |
| 2951 __ j(is_smi, &no_conversion); | 2978 __ j(is_smi, &no_conversion); |
| 2952 __ push(result_register()); | 2979 __ push(result_register()); |
| 2953 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 2980 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
| 2954 __ bind(&no_conversion); | 2981 __ bind(&no_conversion); |
| 2955 context()->Plug(result_register()); | 2982 context()->Plug(result_register()); |
| 2956 break; | 2983 break; |
| 2957 } | 2984 } |
| 2958 | 2985 |
| 2959 case Token::SUB: { | 2986 case Token::SUB: { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3092 is_smi = masm_->CheckSmi(rax); | 3119 is_smi = masm_->CheckSmi(rax); |
| 3093 __ j(is_smi, &done); | 3120 __ j(is_smi, &done); |
| 3094 __ bind(&stub_call); | 3121 __ bind(&stub_call); |
| 3095 // Call stub. Undo operation first. | 3122 // Call stub. Undo operation first. |
| 3096 if (expr->op() == Token::INC) { | 3123 if (expr->op() == Token::INC) { |
| 3097 __ SmiSubConstant(rax, rax, Smi::FromInt(1)); | 3124 __ SmiSubConstant(rax, rax, Smi::FromInt(1)); |
| 3098 } else { | 3125 } else { |
| 3099 __ SmiAddConstant(rax, rax, Smi::FromInt(1)); | 3126 __ SmiAddConstant(rax, rax, Smi::FromInt(1)); |
| 3100 } | 3127 } |
| 3101 } | 3128 } |
| 3129 |
| 3130 // Record position before stub call. |
| 3131 SetSourcePosition(expr->position()); |
| 3132 |
| 3102 // Call stub for +1/-1. | 3133 // Call stub for +1/-1. |
| 3103 GenericBinaryOpStub stub(expr->binary_op(), | 3134 GenericBinaryOpStub stub(expr->binary_op(), |
| 3104 NO_OVERWRITE, | 3135 NO_OVERWRITE, |
| 3105 NO_GENERIC_BINARY_FLAGS); | 3136 NO_GENERIC_BINARY_FLAGS); |
| 3106 stub.GenerateCall(masm_, rax, Smi::FromInt(1)); | 3137 stub.GenerateCall(masm_, rax, Smi::FromInt(1)); |
| 3107 __ bind(&done); | 3138 __ bind(&done); |
| 3108 | 3139 |
| 3109 // Store the value returned in rax. | 3140 // Store the value returned in rax. |
| 3110 switch (assign_type) { | 3141 switch (assign_type) { |
| 3111 case VARIABLE: | 3142 case VARIABLE: |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3432 Register FullCodeGenerator::context_register() { | 3463 Register FullCodeGenerator::context_register() { |
| 3433 return rsi; | 3464 return rsi; |
| 3434 } | 3465 } |
| 3435 | 3466 |
| 3436 | 3467 |
| 3437 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { | 3468 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
| 3438 ASSERT(mode == RelocInfo::CODE_TARGET || | 3469 ASSERT(mode == RelocInfo::CODE_TARGET || |
| 3439 mode == RelocInfo::CODE_TARGET_CONTEXT); | 3470 mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 3440 __ call(ic, mode); | 3471 __ call(ic, mode); |
| 3441 | 3472 |
| 3473 // Crankshaft doesn't need patching of inlined loads and stores. |
| 3474 if (V8::UseCrankshaft()) return; |
| 3475 |
| 3442 // If we're calling a (keyed) load or store stub, we have to mark | 3476 // If we're calling a (keyed) load or store stub, we have to mark |
| 3443 // the call as containing no inlined code so we will not attempt to | 3477 // the call as containing no inlined code so we will not attempt to |
| 3444 // patch it. | 3478 // patch it. |
| 3445 switch (ic->kind()) { | 3479 switch (ic->kind()) { |
| 3446 case Code::LOAD_IC: | 3480 case Code::LOAD_IC: |
| 3447 case Code::KEYED_LOAD_IC: | 3481 case Code::KEYED_LOAD_IC: |
| 3448 case Code::STORE_IC: | 3482 case Code::STORE_IC: |
| 3449 case Code::KEYED_STORE_IC: | 3483 case Code::KEYED_STORE_IC: |
| 3450 __ nop(); // Signals no inlined code. | 3484 __ nop(); // Signals no inlined code. |
| 3451 break; | 3485 break; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3500 __ ret(0); | 3534 __ ret(0); |
| 3501 } | 3535 } |
| 3502 | 3536 |
| 3503 | 3537 |
| 3504 #undef __ | 3538 #undef __ |
| 3505 | 3539 |
| 3506 | 3540 |
| 3507 } } // namespace v8::internal | 3541 } } // namespace v8::internal |
| 3508 | 3542 |
| 3509 #endif // V8_TARGET_ARCH_X64 | 3543 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |