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

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

Issue 523052: More cleanup of slot handling in the nonoptimizing code generator.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 months 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 | Annotate | Revision Log
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 __ movq(rax, Operand(rsp, 0)); 263 __ movq(rax, Operand(rsp, 0));
264 TestAndBranch(rax, &discard, false_label_); 264 TestAndBranch(rax, &discard, false_label_);
265 __ bind(&discard); 265 __ bind(&discard);
266 __ Drop(1); 266 __ Drop(1);
267 __ jmp(true_label_); 267 __ jmp(true_label_);
268 } 268 }
269 } 269 }
270 } 270 }
271 271
272 272
273 template <> 273 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
274 Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source, 274 switch (slot->type()) {
275 Register scratch) {
276 switch (source->type()) {
277 case Slot::PARAMETER: 275 case Slot::PARAMETER:
278 case Slot::LOCAL: 276 case Slot::LOCAL:
279 return Operand(rbp, SlotOffset(source)); 277 return Operand(rbp, SlotOffset(slot));
280 case Slot::CONTEXT: { 278 case Slot::CONTEXT: {
281 int context_chain_length = 279 int context_chain_length =
282 function_->scope()->ContextChainLength(source->var()->scope()); 280 function_->scope()->ContextChainLength(slot->var()->scope());
283 __ LoadContext(scratch, context_chain_length); 281 __ LoadContext(scratch, context_chain_length);
284 return CodeGenerator::ContextOperand(scratch, source->index()); 282 return CodeGenerator::ContextOperand(scratch, slot->index());
285 } 283 }
286 case Slot::LOOKUP: 284 case Slot::LOOKUP:
287 UNIMPLEMENTED(); 285 UNREACHABLE();
288 } 286 }
289 UNREACHABLE(); 287 UNREACHABLE();
290 return Operand(rax, 0); 288 return Operand(rax, 0);
291 } 289 }
292 290
293 291
294 void FastCodeGenerator::Move(Register dst, Slot* source) { 292 void FastCodeGenerator::Move(Register destination, Slot* source) {
295 Operand location = CreateSlotOperand<Operand>(source, dst); 293 MemOperand location = EmitSlotSearch(source, destination);
296 __ movq(dst, location); 294 __ movq(destination, location);
297 } 295 }
298 296
299 297
300 void FastCodeGenerator::Move(Expression::Context context, 298 void FastCodeGenerator::Move(Expression::Context context,
301 Slot* source, 299 Slot* source,
302 Register scratch) { 300 Register scratch) {
303 switch (context) { 301 switch (context) {
304 case Expression::kUninitialized: 302 case Expression::kUninitialized:
305 UNREACHABLE(); 303 UNREACHABLE();
306 case Expression::kEffect: 304 case Expression::kEffect:
307 break; 305 break;
308 case Expression::kValue: { 306 case Expression::kValue: {
309 Operand location = CreateSlotOperand<Operand>(source, scratch); 307 MemOperand location = EmitSlotSearch(source, scratch);
310 __ push(location); 308 __ push(location);
311 break; 309 break;
312 } 310 }
313 case Expression::kTest: 311 case Expression::kTest:
314 case Expression::kValueTest: 312 case Expression::kValueTest:
315 case Expression::kTestValue: 313 case Expression::kTestValue:
316 Move(scratch, source); 314 Move(scratch, source);
317 Move(context, scratch); 315 Move(context, scratch);
318 break; 316 break;
319 } 317 }
(...skipping 16 matching lines...) Expand all
336 Move(context, rax); 334 Move(context, rax);
337 break; 335 break;
338 } 336 }
339 } 337 }
340 338
341 339
342 void FastCodeGenerator::Move(Slot* dst, 340 void FastCodeGenerator::Move(Slot* dst,
343 Register src, 341 Register src,
344 Register scratch1, 342 Register scratch1,
345 Register scratch2) { 343 Register scratch2) {
346 switch (dst->type()) { 344 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
347 case Slot::PARAMETER: 345 ASSERT(!scratch1.is(src) && !scratch2.is(src));
348 case Slot::LOCAL: 346 MemOperand location = EmitSlotSearch(dst, scratch1);
349 __ movq(Operand(rbp, SlotOffset(dst)), src); 347 __ movq(location, src);
350 break; 348 // Emit the write barrier code if the location is in the heap.
351 case Slot::CONTEXT: { 349 if (dst->type() == Slot::CONTEXT) {
352 ASSERT(!src.is(scratch1)); 350 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
353 ASSERT(!src.is(scratch2)); 351 __ RecordWrite(scratch1, offset, src, scratch2);
354 ASSERT(!scratch1.is(scratch2));
355 int context_chain_length =
356 function_->scope()->ContextChainLength(dst->var()->scope());
357 __ LoadContext(scratch1, context_chain_length);
358 __ movq(Operand(scratch1, Context::SlotOffset(dst->index())), src);
359 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
360 __ RecordWrite(scratch1, offset, src, scratch2);
361 break;
362 }
363 case Slot::LOOKUP:
364 UNIMPLEMENTED();
365 } 352 }
366 } 353 }
367 354
368 355
369 void FastCodeGenerator::DropAndMove(Expression::Context context, 356 void FastCodeGenerator::DropAndMove(Expression::Context context,
370 Register source, 357 Register source,
371 int drop_count) { 358 int drop_count) {
372 ASSERT(drop_count > 0); 359 ASSERT(drop_count > 0);
373 switch (context) { 360 switch (context) {
374 case Expression::kUninitialized: 361 case Expression::kUninitialized:
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 ASSERT(var != NULL); // Must have been resolved. 437 ASSERT(var != NULL); // Must have been resolved.
451 Slot* slot = var->slot(); 438 Slot* slot = var->slot();
452 Property* prop = var->AsProperty(); 439 Property* prop = var->AsProperty();
453 440
454 if (slot != NULL) { 441 if (slot != NULL) {
455 switch (slot->type()) { 442 switch (slot->type()) {
456 case Slot::PARAMETER: 443 case Slot::PARAMETER:
457 case Slot::LOCAL: 444 case Slot::LOCAL:
458 if (decl->mode() == Variable::CONST) { 445 if (decl->mode() == Variable::CONST) {
459 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 446 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
460 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); 447 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
461 } else if (decl->fun() != NULL) { 448 } else if (decl->fun() != NULL) {
462 Visit(decl->fun()); 449 Visit(decl->fun());
463 __ pop(Operand(rbp, SlotOffset(var->slot()))); 450 __ pop(Operand(rbp, SlotOffset(slot)));
464 } 451 }
465 break; 452 break;
466 453
467 case Slot::CONTEXT: 454 case Slot::CONTEXT:
455 // We bypass the general EmitSlotSearch because we know more about
456 // this specific context.
457
468 // The variable in the decl always resides in the current context. 458 // The variable in the decl always resides in the current context.
469 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); 459 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
470 if (FLAG_debug_code) { 460 if (FLAG_debug_code) {
471 // Check if we have the correct context pointer. 461 // Check if we have the correct context pointer.
472 __ movq(rbx, 462 __ movq(rbx,
473 CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX)); 463 CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX));
474 __ cmpq(rbx, rsi); 464 __ cmpq(rbx, rsi);
475 __ Check(equal, "Unexpected declaration in current context."); 465 __ Check(equal, "Unexpected declaration in current context.");
476 } 466 }
477 if (decl->mode() == Variable::CONST) { 467 if (decl->mode() == Variable::CONST) {
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 // assignment. Right-hand-side value is passed in rax, variable name in 891 // assignment. Right-hand-side value is passed in rax, variable name in
902 // rcx, and the global object on the stack. 892 // rcx, and the global object on the stack.
903 __ pop(rax); 893 __ pop(rax);
904 __ Move(rcx, var->name()); 894 __ Move(rcx, var->name());
905 __ push(CodeGenerator::GlobalObject()); 895 __ push(CodeGenerator::GlobalObject());
906 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 896 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
907 __ Call(ic, RelocInfo::CODE_TARGET); 897 __ Call(ic, RelocInfo::CODE_TARGET);
908 // Overwrite the global object on the stack with the result if needed. 898 // Overwrite the global object on the stack with the result if needed.
909 DropAndMove(context, rax); 899 DropAndMove(context, rax);
910 900
911 } else if (var->slot()) { 901 } else if (var->slot() != NULL) {
912 Slot* slot = var->slot(); 902 Slot* slot = var->slot();
913 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled.
914 switch (slot->type()) { 903 switch (slot->type()) {
915 case Slot::LOCAL: 904 case Slot::LOCAL:
916 case Slot::PARAMETER: { 905 case Slot::PARAMETER: {
906 Operand target = Operand(rbp, SlotOffset(slot));
917 switch (context) { 907 switch (context) {
918 case Expression::kUninitialized: 908 case Expression::kUninitialized:
919 UNREACHABLE(); 909 UNREACHABLE();
920 case Expression::kEffect: 910 case Expression::kEffect:
921 // Perform assignment and discard value. 911 // Perform assignment and discard value.
922 __ pop(Operand(rbp, SlotOffset(var->slot()))); 912 __ pop(target);
923 break; 913 break;
924 case Expression::kValue: 914 case Expression::kValue:
925 // Perform assignment and preserve value. 915 // Perform assignment and preserve value.
926 __ movq(rax, Operand(rsp, 0)); 916 __ movq(rax, Operand(rsp, 0));
927 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); 917 __ movq(target, rax);
928 break; 918 break;
929 case Expression::kTest: 919 case Expression::kTest:
930 // Perform assignment and test (and discard) value. 920 // Perform assignment and test (and discard) value.
931 __ pop(rax); 921 __ pop(rax);
932 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); 922 __ movq(target, rax);
933 TestAndBranch(rax, true_label_, false_label_); 923 TestAndBranch(rax, true_label_, false_label_);
934 break; 924 break;
935 case Expression::kValueTest: { 925 case Expression::kValueTest: {
936 Label discard; 926 Label discard;
937 __ movq(rax, Operand(rsp, 0)); 927 __ movq(rax, Operand(rsp, 0));
938 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); 928 __ movq(target, rax);
939 TestAndBranch(rax, true_label_, &discard); 929 TestAndBranch(rax, true_label_, &discard);
940 __ bind(&discard); 930 __ bind(&discard);
941 __ addq(rsp, Immediate(kPointerSize)); 931 __ addq(rsp, Immediate(kPointerSize));
942 __ jmp(false_label_); 932 __ jmp(false_label_);
943 break; 933 break;
944 } 934 }
945 case Expression::kTestValue: { 935 case Expression::kTestValue: {
946 Label discard; 936 Label discard;
947 __ movq(rax, Operand(rsp, 0)); 937 __ movq(rax, Operand(rsp, 0));
948 __ movq(Operand(rbp, SlotOffset(var->slot())), rax); 938 __ movq(target, rax);
949 TestAndBranch(rax, &discard, false_label_); 939 TestAndBranch(rax, &discard, false_label_);
950 __ bind(&discard); 940 __ bind(&discard);
951 __ addq(rsp, Immediate(kPointerSize)); 941 __ addq(rsp, Immediate(kPointerSize));
952 __ jmp(true_label_); 942 __ jmp(true_label_);
953 break; 943 break;
954 } 944 }
955 } 945 }
956 break; 946 break;
957 } 947 }
958 948
959 case Slot::CONTEXT: { 949 case Slot::CONTEXT: {
960 int chain_length = 950 MemOperand target = EmitSlotSearch(slot, rcx);
961 function_->scope()->ContextChainLength(slot->var()->scope()); 951 __ pop(rax);
962 if (chain_length > 0) { 952 __ movq(target, rax);
963 // Move up the context chain to the context containing the slot.
964 __ movq(rax,
965 Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX)));
966 // Load the function context (which is the incoming, outer context).
967 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
968 for (int i = 1; i < chain_length; i++) {
969 __ movq(rax,
970 Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)));
971 __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset));
972 }
973 } else { // Slot is in the current context. Generate optimized code.
974 __ movq(rax, rsi); // RecordWrite destroys the object register.
975 }
976 if (FLAG_debug_code) {
977 __ cmpq(rax,
978 Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)));
979 __ Check(equal, "Context Slot chain length wrong.");
980 }
981 __ pop(rcx);
982 __ movq(Operand(rax, Context::SlotOffset(slot->index())), rcx);
983 953
984 // RecordWrite may destroy all its register arguments. 954 // RecordWrite may destroy all its register arguments.
985 if (context == Expression::kValue) { 955 if (context == Expression::kValue) {
986 __ push(rcx); 956 __ push(rax);
987 } else if (context != Expression::kEffect) { 957 } else if (context != Expression::kEffect) {
988 __ movq(rdx, rcx); 958 __ movq(rdx, rax);
989 } 959 }
990 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 960 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
991 __ RecordWrite(rax, offset, rcx, rbx); 961 __ RecordWrite(rcx, offset, rax, rbx);
992 if (context != Expression::kEffect && 962 if (context != Expression::kEffect &&
993 context != Expression::kValue) { 963 context != Expression::kValue) {
994 Move(context, rdx); 964 Move(context, rdx);
995 } 965 }
996 break; 966 break;
997 } 967 }
998 968
999 case Slot::LOOKUP: 969 case Slot::LOOKUP:
1000 UNREACHABLE(); 970 UNREACHABLE();
1001 break; 971 break;
1002 } 972 }
973 } else {
974 // Variables rewritten as properties are not treated as variables in
975 // assignments.
976 UNREACHABLE();
1003 } 977 }
1004 } 978 }
1005 979
1006 980
1007 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 981 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1008 // Assignment to a property, using a named store IC. 982 // Assignment to a property, using a named store IC.
1009 Property* prop = expr->target()->AsProperty(); 983 Property* prop = expr->target()->AsProperty();
1010 ASSERT(prop != NULL); 984 ASSERT(prop != NULL);
1011 ASSERT(prop->key()->AsLiteral() != NULL); 985 ASSERT(prop->key()->AsLiteral() != NULL);
1012 986
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after
1810 __ movq(Operand(rsp, 0), rdx); 1784 __ movq(Operand(rsp, 0), rdx);
1811 // And return. 1785 // And return.
1812 __ ret(0); 1786 __ ret(0);
1813 } 1787 }
1814 1788
1815 1789
1816 #undef __ 1790 #undef __
1817 1791
1818 1792
1819 } } // namespace v8::internal 1793 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698