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

Side by Side Diff: src/arm/fast-codegen-arm.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 | « no previous file | src/fast-codegen.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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 __ ldr(r0, MemOperand(sp, 0)); 274 __ ldr(r0, MemOperand(sp, 0));
275 TestAndBranch(r0, &discard, false_label_); 275 TestAndBranch(r0, &discard, false_label_);
276 __ bind(&discard); 276 __ bind(&discard);
277 __ Drop(1); 277 __ Drop(1);
278 __ jmp(true_label_); 278 __ jmp(true_label_);
279 } 279 }
280 } 280 }
281 } 281 }
282 282
283 283
284 template <> 284 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
285 MemOperand FastCodeGenerator::CreateSlotOperand<MemOperand>( 285 switch (slot->type()) {
286 Slot* source,
287 Register scratch) {
288 switch (source->type()) {
289 case Slot::PARAMETER: 286 case Slot::PARAMETER:
290 case Slot::LOCAL: 287 case Slot::LOCAL:
291 return MemOperand(fp, SlotOffset(source)); 288 return MemOperand(fp, SlotOffset(slot));
292 case Slot::CONTEXT: { 289 case Slot::CONTEXT: {
293 int context_chain_length = 290 int context_chain_length =
294 function_->scope()->ContextChainLength(source->var()->scope()); 291 function_->scope()->ContextChainLength(slot->var()->scope());
295 __ LoadContext(scratch, context_chain_length); 292 __ LoadContext(scratch, context_chain_length);
296 return CodeGenerator::ContextOperand(scratch, source->index()); 293 return CodeGenerator::ContextOperand(scratch, slot->index());
297 } 294 }
298 case Slot::LOOKUP: 295 case Slot::LOOKUP:
299 UNIMPLEMENTED(); 296 UNREACHABLE();
300 } 297 }
301 UNREACHABLE(); 298 UNREACHABLE();
302 return MemOperand(r0, 0); 299 return MemOperand(r0, 0);
303 } 300 }
304 301
305 302
306 void FastCodeGenerator::Move(Register dst, Slot* source) { 303 void FastCodeGenerator::Move(Register destination, Slot* source) {
307 // Use dst as scratch. 304 // Use destination as scratch.
308 MemOperand location = CreateSlotOperand<MemOperand>(source, dst); 305 MemOperand location = EmitSlotSearch(source, destination);
309 __ ldr(dst, location); 306 __ ldr(destination, location);
310 } 307 }
311 308
312 309
313 310
314 void FastCodeGenerator::Move(Expression::Context context, 311 void FastCodeGenerator::Move(Expression::Context context,
315 Slot* source, 312 Slot* source,
316 Register scratch) { 313 Register scratch) {
317 switch (context) { 314 switch (context) {
318 case Expression::kUninitialized: 315 case Expression::kUninitialized:
319 UNREACHABLE(); 316 UNREACHABLE();
(...skipping 24 matching lines...) Expand all
344 Move(context, ip); 341 Move(context, ip);
345 break; 342 break;
346 } 343 }
347 } 344 }
348 345
349 346
350 void FastCodeGenerator::Move(Slot* dst, 347 void FastCodeGenerator::Move(Slot* dst,
351 Register src, 348 Register src,
352 Register scratch1, 349 Register scratch1,
353 Register scratch2) { 350 Register scratch2) {
354 switch (dst->type()) { 351 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
355 case Slot::PARAMETER: 352 ASSERT(!scratch1.is(src) && !scratch2.is(src));
356 case Slot::LOCAL: 353 MemOperand location = EmitSlotSearch(dst, scratch1);
357 __ str(src, MemOperand(fp, SlotOffset(dst))); 354 __ str(src, location);
358 break; 355 // Emit the write barrier code if the location is in the heap.
359 case Slot::CONTEXT: { 356 if (dst->type() == Slot::CONTEXT) {
360 int context_chain_length = 357 __ mov(scratch2, Operand(Context::SlotOffset(dst->index())));
361 function_->scope()->ContextChainLength(dst->var()->scope()); 358 __ RecordWrite(scratch1, scratch2, src);
362 __ LoadContext(scratch1, context_chain_length);
363 int index = Context::SlotOffset(dst->index());
364 __ mov(scratch2, Operand(index));
365 __ str(src, MemOperand(scratch1, index));
366 __ RecordWrite(scratch1, scratch2, src);
367 break;
368 }
369 case Slot::LOOKUP:
370 UNIMPLEMENTED();
371 } 359 }
372 } 360 }
373 361
374 362
375 363
376 void FastCodeGenerator::DropAndMove(Expression::Context context, 364 void FastCodeGenerator::DropAndMove(Expression::Context context,
377 Register source, 365 Register source,
378 int drop_count) { 366 int drop_count) {
379 ASSERT(drop_count > 0); 367 ASSERT(drop_count > 0);
380 switch (context) { 368 switch (context) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 ASSERT(var != NULL); // Must have been resolved. 432 ASSERT(var != NULL); // Must have been resolved.
445 Slot* slot = var->slot(); 433 Slot* slot = var->slot();
446 Property* prop = var->AsProperty(); 434 Property* prop = var->AsProperty();
447 435
448 if (slot != NULL) { 436 if (slot != NULL) {
449 switch (slot->type()) { 437 switch (slot->type()) {
450 case Slot::PARAMETER: 438 case Slot::PARAMETER:
451 case Slot::LOCAL: 439 case Slot::LOCAL:
452 if (decl->mode() == Variable::CONST) { 440 if (decl->mode() == Variable::CONST) {
453 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 441 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
454 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); 442 __ str(ip, MemOperand(fp, SlotOffset(slot)));
455 } else if (decl->fun() != NULL) { 443 } else if (decl->fun() != NULL) {
456 Visit(decl->fun()); 444 Visit(decl->fun());
457 __ pop(ip); 445 __ pop(ip);
458 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); 446 __ str(ip, MemOperand(fp, SlotOffset(slot)));
459 } 447 }
460 break; 448 break;
461 449
462 case Slot::CONTEXT: 450 case Slot::CONTEXT:
451 // We bypass the general EmitSlotSearch because we know more about
452 // this specific context.
453
463 // The variable in the decl always resides in the current context. 454 // The variable in the decl always resides in the current context.
464 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); 455 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
465 if (FLAG_debug_code) { 456 if (FLAG_debug_code) {
466 // Check if we have the correct context pointer. 457 // Check if we have the correct context pointer.
467 __ ldr(r1, 458 __ ldr(r1,
468 CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX)); 459 CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX));
469 __ cmp(r1, cp); 460 __ cmp(r1, cp);
470 __ Check(eq, "Unexpected declaration in current context."); 461 __ Check(eq, "Unexpected declaration in current context.");
471 } 462 }
472 if (decl->mode() == Variable::CONST) { 463 if (decl->mode() == Variable::CONST) {
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 // r2, and the global object on the stack. 896 // r2, and the global object on the stack.
906 __ pop(r0); 897 __ pop(r0);
907 __ mov(r2, Operand(var->name())); 898 __ mov(r2, Operand(var->name()));
908 __ ldr(ip, CodeGenerator::GlobalObject()); 899 __ ldr(ip, CodeGenerator::GlobalObject());
909 __ push(ip); 900 __ push(ip);
910 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 901 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
911 __ Call(ic, RelocInfo::CODE_TARGET); 902 __ Call(ic, RelocInfo::CODE_TARGET);
912 // Overwrite the global object on the stack with the result if needed. 903 // Overwrite the global object on the stack with the result if needed.
913 DropAndMove(context, r0); 904 DropAndMove(context, r0);
914 905
915 } else if (var->slot()) { 906 } else if (var->slot() != NULL) {
916 Slot* slot = var->slot(); 907 Slot* slot = var->slot();
917 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled.
918 switch (slot->type()) { 908 switch (slot->type()) {
919 case Slot::LOCAL: 909 case Slot::LOCAL:
920 case Slot::PARAMETER: { 910 case Slot::PARAMETER: {
911 MemOperand target = MemOperand(fp, SlotOffset(slot));
921 switch (context) { 912 switch (context) {
922 case Expression::kUninitialized: 913 case Expression::kUninitialized:
923 UNREACHABLE(); 914 UNREACHABLE();
924 case Expression::kEffect: 915 case Expression::kEffect:
925 // Perform assignment and discard value. 916 // Perform assignment and discard value.
926 __ pop(r0); 917 __ pop(r0);
927 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); 918 __ str(r0, target);
928 break; 919 break;
929 case Expression::kValue: 920 case Expression::kValue:
930 // Perform assignment and preserve value. 921 // Perform assignment and preserve value.
931 __ ldr(r0, MemOperand(sp)); 922 __ ldr(r0, MemOperand(sp));
932 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); 923 __ str(r0, target);
933 break; 924 break;
934 case Expression::kTest: 925 case Expression::kTest:
935 // Perform assignment and test (and discard) value. 926 // Perform assignment and test (and discard) value.
936 __ pop(r0); 927 __ pop(r0);
937 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); 928 __ str(r0, target);
938 TestAndBranch(r0, true_label_, false_label_); 929 TestAndBranch(r0, true_label_, false_label_);
939 break; 930 break;
940 case Expression::kValueTest: { 931 case Expression::kValueTest: {
941 Label discard; 932 Label discard;
942 __ ldr(r0, MemOperand(sp)); 933 __ ldr(r0, MemOperand(sp));
943 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); 934 __ str(r0, target);
944 TestAndBranch(r0, true_label_, &discard); 935 TestAndBranch(r0, true_label_, &discard);
945 __ bind(&discard); 936 __ bind(&discard);
946 __ pop(); 937 __ pop();
947 __ jmp(false_label_); 938 __ jmp(false_label_);
948 break; 939 break;
949 } 940 }
950 case Expression::kTestValue: { 941 case Expression::kTestValue: {
951 Label discard; 942 Label discard;
952 __ ldr(r0, MemOperand(sp)); 943 __ ldr(r0, MemOperand(sp));
953 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); 944 __ str(r0, target);
954 TestAndBranch(r0, &discard, false_label_); 945 TestAndBranch(r0, &discard, false_label_);
955 __ bind(&discard); 946 __ bind(&discard);
956 __ pop(); 947 __ pop();
957 __ jmp(true_label_); 948 __ jmp(true_label_);
958 break; 949 break;
959 } 950 }
960 } 951 }
961 break; 952 break;
962 } 953 }
963 954
964 case Slot::CONTEXT: { 955 case Slot::CONTEXT: {
965 int chain_length = 956 MemOperand target = EmitSlotSearch(slot, r1);
966 function_->scope()->ContextChainLength(slot->var()->scope()); 957 __ pop(r0);
967 if (chain_length > 0) { 958 __ str(r0, target);
968 // Move up the chain of contexts to the context containing the slot.
969 __ ldr(r0, CodeGenerator::ContextOperand(cp, Context::CLOSURE_INDEX));
970 // Load the function context (which is the incoming, outer context).
971 __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset));
972 for (int i = 1; i < chain_length; i++) {
973 __ ldr(r0,
974 CodeGenerator::ContextOperand(r0, Context::CLOSURE_INDEX));
975 __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset));
976 }
977 } else { // Slot is in the current context. Generate optimized code.
978 __ mov(r0, cp);
979 }
980 // The context may be an intermediate context, not a function context.
981 __ ldr(r0, CodeGenerator::ContextOperand(r0, Context::FCONTEXT_INDEX));
982 __ pop(r1);
983 __ str(r1, CodeGenerator::ContextOperand(r0, slot->index()));
984 959
985 // RecordWrite may destroy all its register arguments. 960 // RecordWrite may destroy all its register arguments.
986 if (context == Expression::kValue) { 961 if (context == Expression::kValue) {
987 __ push(r1); 962 __ push(r0);
988 } else if (context != Expression::kEffect) { 963 } else if (context != Expression::kEffect) {
989 __ mov(r3, r1); 964 __ mov(r3, r0);
990 } 965 }
991 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 966 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
992 967
993 // Update the write barrier for the array store with r0 as the scratch 968 // Update the write barrier for the array store with r0 as the scratch
994 // register. Skip the write barrier if the value written (r1) is a smi. 969 // register. Skip the write barrier if the value written (r1) is a smi.
995 // The smi test is part of RecordWrite on other platforms, not on arm. 970 // The smi test is part of RecordWrite on other platforms, not on arm.
996 Label exit; 971 Label exit;
997 __ tst(r1, Operand(kSmiTagMask)); 972 __ tst(r0, Operand(kSmiTagMask));
998 __ b(eq, &exit); 973 __ b(eq, &exit);
999 974
1000 __ mov(r2, Operand(offset)); 975 __ mov(r2, Operand(offset));
1001 __ RecordWrite(r0, r2, r1); 976 __ RecordWrite(r1, r2, r0);
1002 __ bind(&exit); 977 __ bind(&exit);
1003 if (context != Expression::kEffect && 978 if (context != Expression::kEffect && context != Expression::kValue) {
1004 context != Expression::kValue) {
1005 Move(context, r3); 979 Move(context, r3);
1006 } 980 }
1007 break; 981 break;
1008 } 982 }
1009 983
1010 case Slot::LOOKUP: 984 case Slot::LOOKUP:
1011 UNREACHABLE(); 985 UNREACHABLE();
1012 break; 986 break;
1013 } 987 }
988 } else {
989 // Variables rewritten as properties are not treated as variables in
990 // assignments.
991 UNREACHABLE();
1014 } 992 }
1015 } 993 }
1016 994
1017 995
1018 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 996 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1019 // Assignment to a property, using a named store IC. 997 // Assignment to a property, using a named store IC.
1020 Property* prop = expr->target()->AsProperty(); 998 Property* prop = expr->target()->AsProperty();
1021 ASSERT(prop != NULL); 999 ASSERT(prop != NULL);
1022 ASSERT(prop->key()->AsLiteral() != NULL); 1000 ASSERT(prop->key()->AsLiteral() != NULL);
1023 1001
(...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after
1815 __ pop(result_register()); 1793 __ pop(result_register());
1816 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 1794 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
1817 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 1795 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
1818 __ add(pc, r1, Operand(masm_->CodeObject())); 1796 __ add(pc, r1, Operand(masm_->CodeObject()));
1819 } 1797 }
1820 1798
1821 1799
1822 #undef __ 1800 #undef __
1823 1801
1824 } } // namespace v8::internal 1802 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/fast-codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698