| 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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |