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

Side by Side Diff: src/x64/fast-codegen-x64.cc

Issue 405033: Fast-codegen: Arguments object working on all platforms. (Closed)
Patch Set: Addressed review coments. Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 } else { 69 } else {
70 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 70 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
71 for (int i = 0; i < locals_count; i++) { 71 for (int i = 0; i < locals_count; i++) {
72 __ push(rdx); 72 __ push(rdx);
73 } 73 }
74 } 74 }
75 } 75 }
76 76
77 bool function_in_register = true; 77 bool function_in_register = true;
78 78
79 // Possibly allocate a local context.
80 if (fun->scope()->num_heap_slots() > 0) {
81 Comment cmnt(masm_, "[ Allocate local context");
82 // Argument to NewContext is the function, which is still in rdi.
83 __ push(rdi);
84 __ CallRuntime(Runtime::kNewContext, 1);
85 function_in_register = false;
86 // Context is returned in both rax and rsi. It replaces the context
87 // passed to us. It's saved in the stack and kept live in rsi.
88 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
89
90 // Copy any necessary parameters into the context.
91 int num_parameters = fun->scope()->num_parameters();
92 for (int i = 0; i < num_parameters; i++) {
93 Slot* slot = fun->scope()->parameter(i)->slot();
94 if (slot != NULL && slot->type() == Slot::CONTEXT) {
95 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
96 (num_parameters - 1 - i) * kPointerSize;
97 // Load parameter from stack.
98 __ movq(rax, Operand(rbp, parameter_offset));
99 // Store it in the context
100 __ movq(Operand(rsi, Context::SlotOffset(slot->index())), rax);
101 }
102 }
103 }
104
105 // Possibly allocate an arguments object.
79 Variable* arguments = fun->scope()->arguments()->AsVariable(); 106 Variable* arguments = fun->scope()->arguments()->AsVariable();
80 if (arguments != NULL) { 107 if (arguments != NULL) {
81 // Function uses arguments object. 108 // Arguments object must be allocated after the context object, in
109 // case the "arguments" or ".arguments" variables are in the context.
82 Comment cmnt(masm_, "[ Allocate arguments object"); 110 Comment cmnt(masm_, "[ Allocate arguments object");
83 __ push(rdi); 111 if (function_in_register) {
112 __ push(rdi);
113 } else {
114 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
115 }
84 // The receiver is just before the parameters on the caller's stack. 116 // The receiver is just before the parameters on the caller's stack.
85 __ lea(rdx, Operand(rbp, StandardFrameConstants::kCallerSPOffset + 117 __ lea(rdx, Operand(rbp, StandardFrameConstants::kCallerSPOffset +
86 fun->num_parameters() * kPointerSize)); 118 fun->num_parameters() * kPointerSize));
87 __ push(rdx); 119 __ push(rdx);
88 __ Push(Smi::FromInt(fun->num_parameters())); 120 __ Push(Smi::FromInt(fun->num_parameters()));
89 // Arguments to ArgumentsAccessStub: 121 // Arguments to ArgumentsAccessStub:
90 // function, receiver address, parameter count. 122 // function, receiver address, parameter count.
91 // The stub will rewrite receiver and parameter count if the previous 123 // The stub will rewrite receiver and parameter count if the previous
92 // stack frame was an arguments adapter frame. 124 // stack frame was an arguments adapter frame.
93 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 125 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
94 __ CallStub(&stub); 126 __ CallStub(&stub);
95 // Store new arguments object in both "arguments" and ".arguments" slots. 127 // Store new arguments object in both "arguments" and ".arguments" slots.
96 __ movq(Operand(rbp, SlotOffset(arguments->slot())), rax); 128 __ movq(rcx, rax);
129 Move(arguments->slot(), rax, rbx, rdx);
97 Slot* dot_arguments_slot = 130 Slot* dot_arguments_slot =
98 fun->scope()->arguments_shadow()->AsVariable()->slot(); 131 fun->scope()->arguments_shadow()->AsVariable()->slot();
99 __ movq(Operand(rbp, SlotOffset(dot_arguments_slot)), rax); 132 Move(dot_arguments_slot, rcx, rbx, rdx);
100 function_in_register = false;
101 }
102
103 // Possibly allocate a local context.
104 if (fun->scope()->num_heap_slots() > 0) {
105 Comment cmnt(masm_, "[ Allocate local context");
106 if (function_in_register) {
107 // Argument to NewContext is the function, still in rdi.
108 __ push(rdi);
109 } else {
110 // Argument to NewContext is the function, no longer in rdi.
111 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
112 }
113 __ CallRuntime(Runtime::kNewContext, 1);
114 // Context is returned in both rax and rsi. It replaces the context
115 // passed to us. It's saved in the stack and kept live in rsi.
116 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
117 #ifdef DEBUG
118 // Assert we do not have to copy any parameters into the context.
119 for (int i = 0, len = fun->scope()->num_parameters(); i < len; i++) {
120 Slot* slot = fun->scope()->parameter(i)->slot();
121 ASSERT(slot != NULL && slot->type() != Slot::CONTEXT);
122 }
123 #endif
124 } 133 }
125 134
126 { Comment cmnt(masm_, "[ Stack check"); 135 { Comment cmnt(masm_, "[ Stack check");
127 Label ok; 136 Label ok;
128 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 137 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
129 __ j(above_equal, &ok); 138 __ j(above_equal, &ok);
130 StackCheckStub stub; 139 StackCheckStub stub;
131 __ CallStub(&stub); 140 __ CallStub(&stub);
132 __ bind(&ok); 141 __ bind(&ok);
133 } 142 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 TestAndBranch(source, &discard, false_label_); 229 TestAndBranch(source, &discard, false_label_);
221 __ bind(&discard); 230 __ bind(&discard);
222 __ addq(rsp, Immediate(kPointerSize)); 231 __ addq(rsp, Immediate(kPointerSize));
223 __ jmp(true_label_); 232 __ jmp(true_label_);
224 break; 233 break;
225 } 234 }
226 } 235 }
227 } 236 }
228 237
229 238
230 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { 239 template <>
240 Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source,
241 Register scratch) {
242 switch (source->type()) {
243 case Slot::PARAMETER:
244 case Slot::LOCAL:
245 return Operand(rbp, SlotOffset(source));
246 case Slot::CONTEXT: {
247 int context_chain_length =
248 function_->scope()->ContextChainLength(source->var()->scope());
249 __ LoadContext(scratch, context_chain_length);
250 return CodeGenerator::ContextOperand(scratch, source->index());
251 break;
252 }
253 case Slot::LOOKUP:
254 UNIMPLEMENTED();
255 // Fall-through.
256 default:
257 UNREACHABLE();
258 return Operand(rax, 0); // Dead code to make the compiler happy.
259 }
260 }
261
262
263 void FastCodeGenerator::Move(Register dst, Slot* source) {
264 Operand location = CreateSlotOperand<Operand>(source, dst);
265 __ movq(dst, location);
266 }
267
268
269 void FastCodeGenerator::Move(Expression::Context context,
270 Slot* source,
271 Register scratch) {
231 switch (context) { 272 switch (context) {
232 case Expression::kUninitialized: 273 case Expression::kUninitialized:
233 UNREACHABLE(); 274 UNREACHABLE();
234 case Expression::kEffect: 275 case Expression::kEffect:
235 break; 276 break;
236 case Expression::kValue: 277 case Expression::kValue: {
237 __ push(Operand(rbp, SlotOffset(source))); 278 Operand location = CreateSlotOperand<Operand>(source, scratch);
279 __ push(location);
238 break; 280 break;
281 }
239 case Expression::kTest: // Fall through. 282 case Expression::kTest: // Fall through.
240 case Expression::kValueTest: // Fall through. 283 case Expression::kValueTest: // Fall through.
241 case Expression::kTestValue: 284 case Expression::kTestValue:
242 __ movq(rax, Operand(rbp, SlotOffset(source))); 285 Move(scratch, source);
243 Move(context, rax); 286 Move(context, scratch);
244 break; 287 break;
245 } 288 }
246 } 289 }
247 290
248 291
249 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { 292 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
250 switch (context) { 293 switch (context) {
251 case Expression::kUninitialized: 294 case Expression::kUninitialized:
252 UNREACHABLE(); 295 UNREACHABLE();
253 case Expression::kEffect: 296 case Expression::kEffect:
254 break; 297 break;
255 case Expression::kValue: 298 case Expression::kValue:
256 __ Push(expr->handle()); 299 __ Push(expr->handle());
257 break; 300 break;
258 case Expression::kTest: // Fall through. 301 case Expression::kTest: // Fall through.
259 case Expression::kValueTest: // Fall through. 302 case Expression::kValueTest: // Fall through.
260 case Expression::kTestValue: 303 case Expression::kTestValue:
261 __ Move(rax, expr->handle()); 304 __ Move(rax, expr->handle());
262 Move(context, rax); 305 Move(context, rax);
263 break; 306 break;
264 } 307 }
265 } 308 }
266 309
267 310
311 void FastCodeGenerator::Move(Slot* dst,
312 Register src,
313 Register scratch1,
314 Register scratch2) {
315 switch (dst->type()) {
316 case Slot::PARAMETER:
317 case Slot::LOCAL:
318 __ movq(Operand(rbp, SlotOffset(dst)), src);
319 break;
320 case Slot::CONTEXT: {
321 ASSERT(!src.is(scratch1));
322 ASSERT(!src.is(scratch2));
323 ASSERT(!scratch1.is(scratch2));
324 int context_chain_length =
325 function_->scope()->ContextChainLength(dst->var()->scope());
326 __ LoadContext(scratch1, context_chain_length);
327 __ movq(Operand(scratch1, Context::SlotOffset(dst->index())), src);
328 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
329 __ RecordWrite(scratch1, offset, src, scratch2);
330 break;
331 }
332 case Slot::LOOKUP:
333 UNIMPLEMENTED();
334 default:
335 UNREACHABLE();
336 }
337 }
338
339
268 void FastCodeGenerator::DropAndMove(Expression::Context context, 340 void FastCodeGenerator::DropAndMove(Expression::Context context,
269 Register source) { 341 Register source,
342 int drop_count) {
343 ASSERT(drop_count > 0);
270 switch (context) { 344 switch (context) {
271 case Expression::kUninitialized: 345 case Expression::kUninitialized:
272 UNREACHABLE(); 346 UNREACHABLE();
273 case Expression::kEffect: 347 case Expression::kEffect:
274 __ addq(rsp, Immediate(kPointerSize)); 348 __ addq(rsp, Immediate(drop_count * kPointerSize));
275 break; 349 break;
276 case Expression::kValue: 350 case Expression::kValue:
351 if (drop_count > 1) {
352 __ addq(rsp, Immediate((drop_count - 1) * kPointerSize));
353 }
277 __ movq(Operand(rsp, 0), source); 354 __ movq(Operand(rsp, 0), source);
278 break; 355 break;
279 case Expression::kTest: 356 case Expression::kTest:
280 ASSERT(!source.is(rsp)); 357 ASSERT(!source.is(rsp));
281 __ addq(rsp, Immediate(kPointerSize)); 358 __ addq(rsp, Immediate(drop_count * kPointerSize));
282 TestAndBranch(source, true_label_, false_label_); 359 TestAndBranch(source, true_label_, false_label_);
283 break; 360 break;
284 case Expression::kValueTest: { 361 case Expression::kValueTest: {
285 Label discard; 362 Label discard;
363 if (drop_count > 1) {
364 __ addq(rsp, Immediate((drop_count - 1) * kPointerSize));
365 }
286 __ movq(Operand(rsp, 0), source); 366 __ movq(Operand(rsp, 0), source);
287 TestAndBranch(source, true_label_, &discard); 367 TestAndBranch(source, true_label_, &discard);
288 __ bind(&discard); 368 __ bind(&discard);
289 __ addq(rsp, Immediate(kPointerSize)); 369 __ addq(rsp, Immediate(kPointerSize));
290 __ jmp(false_label_); 370 __ jmp(false_label_);
291 break; 371 break;
292 } 372 }
293 case Expression::kTestValue: { 373 case Expression::kTestValue: {
294 Label discard; 374 Label discard;
295 __ movq(Operand(rsp, 0), source); 375 __ movq(Operand(rsp, 0), source);
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 546 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
467 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 547 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
468 // A test rax instruction following the call is used by the IC to 548 // A test rax instruction following the call is used by the IC to
469 // indicate that the inobject property case was inlined. Ensure there 549 // indicate that the inobject property case was inlined. Ensure there
470 // is no test rax instruction here. 550 // is no test rax instruction here.
471 __ nop(); 551 __ nop();
472 552
473 DropAndMove(expr->context(), rax); 553 DropAndMove(expr->context(), rax);
474 } else if (rewrite->AsSlot() != NULL) { 554 } else if (rewrite->AsSlot() != NULL) {
475 Slot* slot = rewrite->AsSlot(); 555 Slot* slot = rewrite->AsSlot();
476 switch (slot->type()) { 556 if (FLAG_debug_code) {
477 case Slot::LOCAL: 557 switch (slot->type()) {
478 case Slot::PARAMETER: { 558 case Slot::LOCAL:
479 Comment cmnt(masm_, "Stack slot"); 559 case Slot::PARAMETER: {
480 Move(expr->context(), slot); 560 Comment cmnt(masm_, "Stack slot");
481 break; 561 break;
562 }
563 case Slot::CONTEXT: {
564 Comment cmnt(masm_, "Context slot");
565 break;
566 }
567 case Slot::LOOKUP:
568 UNIMPLEMENTED();
569 break;
570 default:
571 UNREACHABLE();
482 } 572 }
483
484 case Slot::CONTEXT: {
485 Comment cmnt(masm_, "Context slot");
486 int chain_length =
487 function_->scope()->ContextChainLength(slot->var()->scope());
488 if (chain_length > 0) {
489 // Move up the chain of contexts to the context containing the slot.
490 __ movq(rax,
491 Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX)));
492 // Load the function context (which is the incoming, outer context).
493 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
494 for (int i = 1; i < chain_length; i++) {
495 __ movq(rax,
496 Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)));
497 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
498 }
499 // The context may be an intermediate context, not a function context.
500 __ movq(rax,
501 Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)));
502 } else { // Slot is in the current function context.
503 // The context may be an intermediate context, not a function context.
504 __ movq(rax,
505 Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX)));
506 }
507 __ movq(rax, Operand(rax, Context::SlotOffset(slot->index())));
508 Move(expr->context(), rax);
509 break;
510 }
511
512 case Slot::LOOKUP:
513 UNREACHABLE();
514 break;
515 } 573 }
574 Move(expr->context(), slot, rax);
516 } else { 575 } else {
517 // The parameter variable has been rewritten into an explict access to 576 // A variable has been rewritten into an explicit access to
518 // the arguments object. 577 // an object property.
519 Property* property = rewrite->AsProperty(); 578 Property* property = rewrite->AsProperty();
520 ASSERT_NOT_NULL(property); 579 ASSERT_NOT_NULL(property);
521 ASSERT_EQ(expr->context(), property->context()); 580
522 Visit(property); 581 // Currently the only parameter expressions that can occur are
582 // on the form "slot[literal]".
583
584 // Check that the object is in a slot.
585 Variable* object = property->obj()->AsVariableProxy()->AsVariable();
586 ASSERT_NOT_NULL(object);
587 Slot* object_slot = object->slot();
588 ASSERT_NOT_NULL(object_slot);
589
590 // Load the object.
591 Move(Expression::kValue, object_slot, rax);
592
593 // Check that the key is a smi.
594 Literal* key_literal = property->key()->AsLiteral();
595 ASSERT_NOT_NULL(key_literal);
596 ASSERT(key_literal->handle()->IsSmi());
597
598 // Load the key.
599 Move(Expression::kValue, key_literal);
600
601 // Do a KEYED property load.
602 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
603 __ call(ic, RelocInfo::CODE_TARGET);
604 // Notice: We must not have a "test rax, ..." instruction after
605 // the call. It is treated specially by the LoadIC code.
606
607 // Drop key and object left on the stack by IC, and push the result.
608 DropAndMove(expr->context(), rax, 2);
523 } 609 }
524 } 610 }
525 611
526 612
527 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 613 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
528 Comment cmnt(masm_, "[ RegExpLiteral"); 614 Comment cmnt(masm_, "[ RegExpLiteral");
529 Label done; 615 Label done;
530 // Registers will be used as follows: 616 // Registers will be used as follows:
531 // rdi = JS function. 617 // rdi = JS function.
532 // rbx = literals array. 618 // rbx = literals array.
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 // assignment. Right-hand-side value is passed in rax, variable name in 860 // assignment. Right-hand-side value is passed in rax, variable name in
775 // rcx, and the global object on the stack. 861 // rcx, and the global object on the stack.
776 __ pop(rax); 862 __ pop(rax);
777 __ Move(rcx, var->name()); 863 __ Move(rcx, var->name());
778 __ push(CodeGenerator::GlobalObject()); 864 __ push(CodeGenerator::GlobalObject());
779 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 865 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
780 __ Call(ic, RelocInfo::CODE_TARGET); 866 __ Call(ic, RelocInfo::CODE_TARGET);
781 // Overwrite the global object on the stack with the result if needed. 867 // Overwrite the global object on the stack with the result if needed.
782 DropAndMove(expr->context(), rax); 868 DropAndMove(expr->context(), rax);
783 869
784 } else { 870 } else if (var->slot()) {
785 Slot* slot = var->slot(); 871 Slot* slot = var->slot();
786 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled. 872 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled.
787 switch (slot->type()) { 873 switch (slot->type()) {
788 case Slot::LOCAL: 874 case Slot::LOCAL:
789 case Slot::PARAMETER: { 875 case Slot::PARAMETER: {
790 switch (expr->context()) { 876 switch (expr->context()) {
791 case Expression::kUninitialized: 877 case Expression::kUninitialized:
792 UNREACHABLE(); 878 UNREACHABLE();
793 case Expression::kEffect: 879 case Expression::kEffect:
794 // Perform assignment and discard value. 880 // Perform assignment and discard value.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 expr->context() != Expression::kValue) { 952 expr->context() != Expression::kValue) {
867 Move(expr->context(), rdx); 953 Move(expr->context(), rdx);
868 } 954 }
869 break; 955 break;
870 } 956 }
871 957
872 case Slot::LOOKUP: 958 case Slot::LOOKUP:
873 UNREACHABLE(); 959 UNREACHABLE();
874 break; 960 break;
875 } 961 }
962 } else {
963 Property* property = var->AsProperty();
964 ASSERT_NOT_NULL(property);
965 // A variable has been rewritten into a property on an object.
966
967 // Load object and key onto the stack.
968 Slot* object_slot = property->obj()->AsSlot();
969 ASSERT_NOT_NULL(object_slot);
970 Move(Expression::kValue, object_slot, rax);
971
972 Literal* key_literal = property->key()->AsLiteral();
973 ASSERT_NOT_NULL(key_literal);
974 Move(Expression::kValue, key_literal);
975
976 // Value to store was pushed before object and key on the stack.
977 __ movq(rax, Operand(rsp, 2 * kPointerSize));
978
979 // Arguments to ic is value in rax, object and key on stack.
980 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
981 __ call(ic, RelocInfo::CODE_TARGET);
982
983 if (expr->context() == Expression::kEffect) {
984 __ addq(rsp, Immediate(3 * kPointerSize));
985 } else if (expr->context() == Expression::kValue) {
986 // Value is still on the stack in rsp[2 * kPointerSize]
987 __ addq(rsp, Immediate(2 * kPointerSize));
988 } else {
989 __ movq(rax, Operand(rsp, 2 * kPointerSize));
990 DropAndMove(expr->context(), rax, 3);
991 }
876 } 992 }
877 } 993 }
878 994
879 995
880 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 996 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
881 // Assignment to a property, using a named store IC. 997 // Assignment to a property, using a named store IC.
882 Property* prop = expr->target()->AsProperty(); 998 Property* prop = expr->target()->AsProperty();
883 ASSERT(prop != NULL); 999 ASSERT(prop != NULL);
884 ASSERT(prop->key()->AsLiteral() != NULL); 1000 ASSERT(prop->key()->AsLiteral() != NULL);
885 1001
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1078 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
963 __ call(ic, RelocInfo::CODE_TARGET); 1079 __ call(ic, RelocInfo::CODE_TARGET);
964 // By emitting a nop we make sure that we do not have a "test rax,..." 1080 // By emitting a nop we make sure that we do not have a "test rax,..."
965 // instruction after the call it is treated specially by the LoadIC code. 1081 // instruction after the call it is treated specially by the LoadIC code.
966 __ nop(); 1082 __ nop();
967 } else { 1083 } else {
968 // Do a KEYED property load. 1084 // Do a KEYED property load.
969 Visit(expr->key()); 1085 Visit(expr->key());
970 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1086 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
971 __ call(ic, RelocInfo::CODE_TARGET); 1087 __ call(ic, RelocInfo::CODE_TARGET);
972 // By emitting a nop we make sure that we do not have a "test rax,..." 1088 // Notice: We must not have a "test rax, ..." instruction after
973 // instruction after the call it is treated specially by the LoadIC code. 1089 // the call. It is treated specially by the LoadIC code.
974 __ nop(); 1090
975 // Drop key left on the stack by IC. 1091 // Drop key left on the stack by IC.
976 __ addq(rsp, Immediate(kPointerSize)); 1092 __ addq(rsp, Immediate(kPointerSize));
977 } 1093 }
978 DropAndMove(expr->context(), rax); 1094 DropAndMove(expr->context(), rax);
979 } 1095 }
980 1096
981 1097
982 void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info) { 1098 void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info) {
983 // Code common for calls using the IC. 1099 // Code common for calls using the IC.
984 ZoneList<Expression*>* args = expr->arguments(); 1100 ZoneList<Expression*>* args = expr->arguments();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 EmitCallWithIC(expr, RelocInfo::CODE_TARGET); 1163 EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
1048 } else { 1164 } else {
1049 // Call to a keyed property, use keyed load IC followed by function 1165 // Call to a keyed property, use keyed load IC followed by function
1050 // call. 1166 // call.
1051 Visit(prop->obj()); 1167 Visit(prop->obj());
1052 Visit(prop->key()); 1168 Visit(prop->key());
1053 // Record source code position for IC call. 1169 // Record source code position for IC call.
1054 SetSourcePosition(prop->position()); 1170 SetSourcePosition(prop->position());
1055 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1171 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1056 __ call(ic, RelocInfo::CODE_TARGET); 1172 __ call(ic, RelocInfo::CODE_TARGET);
1057 // By emitting a nop we make sure that we do not have a "test eax,..." 1173 // By emitting a nop we make sure that we do not have a "test rax,..."
1058 // instruction after the call it is treated specially by the LoadIC code. 1174 // instruction after the call it is treated specially by the LoadIC code.
1059 __ nop(); 1175 __ nop();
1060 // Drop key left on the stack by IC. 1176 // Drop key left on the stack by IC.
1061 __ addq(rsp, Immediate(kPointerSize)); 1177 __ addq(rsp, Immediate(kPointerSize));
1062 // Pop receiver. 1178 // Pop receiver.
1063 __ pop(rbx); 1179 __ pop(rbx);
1064 // Push result (function). 1180 // Push result (function).
1065 __ push(rax); 1181 __ push(rax);
1066 // Push receiver object on stack. 1182 // Push receiver object on stack.
1067 if (prop->is_synthetic()) { 1183 if (prop->is_synthetic()) {
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
1548 true_label_ = saved_true; 1664 true_label_ = saved_true;
1549 false_label_ = saved_false; 1665 false_label_ = saved_false;
1550 // Convert current context to test context: End post-test code. 1666 // Convert current context to test context: End post-test code.
1551 } 1667 }
1552 1668
1553 1669
1554 #undef __ 1670 #undef __
1555 1671
1556 1672
1557 } } // namespace v8::internal 1673 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698