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 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 __ mov(eax, Operand(esp, 0)); | 254 __ mov(eax, Operand(esp, 0)); |
255 TestAndBranch(eax, &discard, false_label_); | 255 TestAndBranch(eax, &discard, false_label_); |
256 __ bind(&discard); | 256 __ bind(&discard); |
257 __ Drop(1); | 257 __ Drop(1); |
258 __ jmp(true_label_); | 258 __ jmp(true_label_); |
259 } | 259 } |
260 } | 260 } |
261 } | 261 } |
262 | 262 |
263 | 263 |
264 template <> | 264 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
265 Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source, | 265 switch (slot->type()) { |
266 Register scratch) { | |
267 switch (source->type()) { | |
268 case Slot::PARAMETER: | 266 case Slot::PARAMETER: |
269 case Slot::LOCAL: | 267 case Slot::LOCAL: |
270 return Operand(ebp, SlotOffset(source)); | 268 return Operand(ebp, SlotOffset(slot)); |
271 case Slot::CONTEXT: { | 269 case Slot::CONTEXT: { |
272 int context_chain_length = | 270 int context_chain_length = |
273 function_->scope()->ContextChainLength(source->var()->scope()); | 271 function_->scope()->ContextChainLength(slot->var()->scope()); |
274 __ LoadContext(scratch, context_chain_length); | 272 __ LoadContext(scratch, context_chain_length); |
275 return CodeGenerator::ContextOperand(scratch, source->index()); | 273 return CodeGenerator::ContextOperand(scratch, slot->index()); |
276 } | 274 } |
277 case Slot::LOOKUP: | 275 case Slot::LOOKUP: |
278 UNIMPLEMENTED(); | 276 UNREACHABLE(); |
279 } | 277 } |
280 UNREACHABLE(); | 278 UNREACHABLE(); |
281 return Operand(eax, 0); | 279 return Operand(eax, 0); |
282 } | 280 } |
283 | 281 |
284 | 282 |
285 void FastCodeGenerator::Move(Register dst, Slot* source) { | 283 void FastCodeGenerator::Move(Register destination, Slot* source) { |
286 Operand location = CreateSlotOperand<Operand>(source, dst); | 284 MemOperand location = EmitSlotSearch(source, destination); |
287 __ mov(dst, location); | 285 __ mov(destination, location); |
288 } | 286 } |
289 | 287 |
290 | 288 |
291 void FastCodeGenerator::Move(Expression::Context context, | 289 void FastCodeGenerator::Move(Expression::Context context, |
292 Slot* source, | 290 Slot* source, |
293 Register scratch) { | 291 Register scratch) { |
294 switch (context) { | 292 switch (context) { |
295 case Expression::kUninitialized: | 293 case Expression::kUninitialized: |
296 UNREACHABLE(); | 294 UNREACHABLE(); |
297 case Expression::kEffect: | 295 case Expression::kEffect: |
298 break; | 296 break; |
299 case Expression::kValue: { | 297 case Expression::kValue: { |
300 Operand location = CreateSlotOperand<Operand>(source, scratch); | 298 MemOperand location = EmitSlotSearch(source, scratch); |
301 __ push(location); | 299 __ push(location); |
302 break; | 300 break; |
303 } | 301 } |
304 case Expression::kTest: | 302 case Expression::kTest: |
305 case Expression::kValueTest: | 303 case Expression::kValueTest: |
306 case Expression::kTestValue: | 304 case Expression::kTestValue: |
307 Move(scratch, source); | 305 Move(scratch, source); |
308 Move(context, scratch); | 306 Move(context, scratch); |
309 break; | 307 break; |
310 } | 308 } |
(...skipping 16 matching lines...) Expand all Loading... |
327 Move(context, eax); | 325 Move(context, eax); |
328 break; | 326 break; |
329 } | 327 } |
330 } | 328 } |
331 | 329 |
332 | 330 |
333 void FastCodeGenerator::Move(Slot* dst, | 331 void FastCodeGenerator::Move(Slot* dst, |
334 Register src, | 332 Register src, |
335 Register scratch1, | 333 Register scratch1, |
336 Register scratch2) { | 334 Register scratch2) { |
337 switch (dst->type()) { | 335 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
338 case Slot::PARAMETER: | 336 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
339 case Slot::LOCAL: | 337 MemOperand location = EmitSlotSearch(dst, scratch1); |
340 __ mov(Operand(ebp, SlotOffset(dst)), src); | 338 __ mov(location, src); |
341 break; | 339 // Emit the write barrier code if the location is in the heap. |
342 case Slot::CONTEXT: { | 340 if (dst->type() == Slot::CONTEXT) { |
343 ASSERT(!src.is(scratch1)); | 341 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
344 ASSERT(!src.is(scratch2)); | 342 __ RecordWrite(scratch1, offset, src, scratch2); |
345 ASSERT(!scratch1.is(scratch2)); | |
346 int context_chain_length = | |
347 function_->scope()->ContextChainLength(dst->var()->scope()); | |
348 __ LoadContext(scratch1, context_chain_length); | |
349 __ mov(Operand(scratch1, Context::SlotOffset(dst->index())), src); | |
350 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | |
351 __ RecordWrite(scratch1, offset, src, scratch2); | |
352 break; | |
353 } | |
354 case Slot::LOOKUP: | |
355 UNIMPLEMENTED(); | |
356 } | 343 } |
357 } | 344 } |
358 | 345 |
359 | 346 |
360 void FastCodeGenerator::DropAndMove(Expression::Context context, | 347 void FastCodeGenerator::DropAndMove(Expression::Context context, |
361 Register source, | 348 Register source, |
362 int count) { | 349 int count) { |
363 ASSERT(count > 0); | 350 ASSERT(count > 0); |
364 switch (context) { | 351 switch (context) { |
365 case Expression::kUninitialized: | 352 case Expression::kUninitialized: |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 Variable* var = decl->proxy()->var(); | 428 Variable* var = decl->proxy()->var(); |
442 ASSERT(var != NULL); // Must have been resolved. | 429 ASSERT(var != NULL); // Must have been resolved. |
443 Slot* slot = var->slot(); | 430 Slot* slot = var->slot(); |
444 Property* prop = var->AsProperty(); | 431 Property* prop = var->AsProperty(); |
445 | 432 |
446 if (slot != NULL) { | 433 if (slot != NULL) { |
447 switch (slot->type()) { | 434 switch (slot->type()) { |
448 case Slot::PARAMETER: | 435 case Slot::PARAMETER: |
449 case Slot::LOCAL: | 436 case Slot::LOCAL: |
450 if (decl->mode() == Variable::CONST) { | 437 if (decl->mode() == Variable::CONST) { |
451 __ mov(Operand(ebp, SlotOffset(var->slot())), | 438 __ mov(Operand(ebp, SlotOffset(slot)), |
452 Immediate(Factory::the_hole_value())); | 439 Immediate(Factory::the_hole_value())); |
453 } else if (decl->fun() != NULL) { | 440 } else if (decl->fun() != NULL) { |
454 Visit(decl->fun()); | 441 Visit(decl->fun()); |
455 __ pop(Operand(ebp, SlotOffset(var->slot()))); | 442 __ pop(Operand(ebp, SlotOffset(slot))); |
456 } | 443 } |
457 break; | 444 break; |
458 | 445 |
459 case Slot::CONTEXT: | 446 case Slot::CONTEXT: |
| 447 // We bypass the general EmitSlotSearch because we know more about |
| 448 // this specific context. |
| 449 |
460 // The variable in the decl always resides in the current context. | 450 // The variable in the decl always resides in the current context. |
461 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); | 451 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); |
462 if (FLAG_debug_code) { | 452 if (FLAG_debug_code) { |
463 // Check if we have the correct context pointer. | 453 // Check if we have the correct context pointer. |
464 __ mov(ebx, | 454 __ mov(ebx, |
465 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); | 455 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); |
466 __ cmp(ebx, Operand(esi)); | 456 __ cmp(ebx, Operand(esi)); |
467 __ Check(equal, "Unexpected declaration in current context."); | 457 __ Check(equal, "Unexpected declaration in current context."); |
468 } | 458 } |
469 if (decl->mode() == Variable::CONST) { | 459 if (decl->mode() == Variable::CONST) { |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 887 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
898 __ call(ic, RelocInfo::CODE_TARGET); | 888 __ call(ic, RelocInfo::CODE_TARGET); |
899 // Overwrite the receiver on the stack with the result if needed. | 889 // Overwrite the receiver on the stack with the result if needed. |
900 DropAndMove(context, eax); | 890 DropAndMove(context, eax); |
901 | 891 |
902 } else if (var->slot() != NULL) { | 892 } else if (var->slot() != NULL) { |
903 Slot* slot = var->slot(); | 893 Slot* slot = var->slot(); |
904 switch (slot->type()) { | 894 switch (slot->type()) { |
905 case Slot::LOCAL: | 895 case Slot::LOCAL: |
906 case Slot::PARAMETER: { | 896 case Slot::PARAMETER: { |
907 Operand target = Operand(ebp, SlotOffset(var->slot())); | 897 Operand target = Operand(ebp, SlotOffset(slot)); |
908 switch (context) { | 898 switch (context) { |
909 case Expression::kUninitialized: | 899 case Expression::kUninitialized: |
910 UNREACHABLE(); | 900 UNREACHABLE(); |
911 case Expression::kEffect: | 901 case Expression::kEffect: |
912 // Perform assignment and discard value. | 902 // Perform assignment and discard value. |
913 __ pop(target); | 903 __ pop(target); |
914 break; | 904 break; |
915 case Expression::kValue: | 905 case Expression::kValue: |
916 // Perform assignment and preserve value. | 906 // Perform assignment and preserve value. |
917 __ mov(eax, Operand(esp, 0)); | 907 __ mov(eax, Operand(esp, 0)); |
(...skipping 23 matching lines...) Expand all Loading... |
941 __ bind(&discard); | 931 __ bind(&discard); |
942 __ add(Operand(esp), Immediate(kPointerSize)); | 932 __ add(Operand(esp), Immediate(kPointerSize)); |
943 __ jmp(true_label_); | 933 __ jmp(true_label_); |
944 break; | 934 break; |
945 } | 935 } |
946 } | 936 } |
947 break; | 937 break; |
948 } | 938 } |
949 | 939 |
950 case Slot::CONTEXT: { | 940 case Slot::CONTEXT: { |
951 int chain_length = | 941 MemOperand target = EmitSlotSearch(slot, ecx); |
952 function_->scope()->ContextChainLength(slot->var()->scope()); | 942 __ pop(eax); |
953 if (chain_length > 0) { | 943 __ mov(target, eax); |
954 // Move up the context chain to the context containing the slot. | |
955 __ mov(eax, | |
956 Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); | |
957 // Load the function context (which is the incoming, outer context). | |
958 __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); | |
959 for (int i = 1; i < chain_length; i++) { | |
960 __ mov(eax, | |
961 Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX))); | |
962 __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); | |
963 } | |
964 } else { // Slot is in the current context. Generate optimized code. | |
965 __ mov(eax, esi); // RecordWrite destroys the object register. | |
966 } | |
967 if (FLAG_debug_code) { | |
968 __ cmp(eax, | |
969 Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX))); | |
970 __ Check(equal, "Context Slot chain length wrong."); | |
971 } | |
972 __ pop(ecx); | |
973 __ mov(Operand(eax, Context::SlotOffset(slot->index())), ecx); | |
974 | 944 |
975 // RecordWrite may destroy all its register arguments. | 945 // RecordWrite may destroy all its register arguments. |
976 if (context == Expression::kValue) { | 946 if (context == Expression::kValue) { |
977 __ push(ecx); | 947 __ push(eax); |
978 } else if (context != Expression::kEffect) { | 948 } else if (context != Expression::kEffect) { |
979 __ mov(edx, ecx); | 949 __ mov(edx, eax); |
980 } | 950 } |
981 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 951 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
982 __ RecordWrite(eax, offset, ecx, ebx); | 952 __ RecordWrite(ecx, offset, eax, ebx); |
983 if (context != Expression::kEffect && | 953 if (context != Expression::kEffect && |
984 context != Expression::kValue) { | 954 context != Expression::kValue) { |
985 Move(context, edx); | 955 Move(context, edx); |
986 } | 956 } |
987 break; | 957 break; |
988 } | 958 } |
989 | 959 |
990 case Slot::LOOKUP: | 960 case Slot::LOOKUP: |
991 UNREACHABLE(); | 961 UNREACHABLE(); |
992 break; | 962 break; |
993 } | 963 } |
| 964 } else { |
| 965 // Variables rewritten as properties are not treated as variables in |
| 966 // assignments. |
| 967 UNREACHABLE(); |
994 } | 968 } |
995 } | 969 } |
996 | 970 |
997 | 971 |
998 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 972 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
999 // Assignment to a property, using a named store IC. | 973 // Assignment to a property, using a named store IC. |
1000 Property* prop = expr->target()->AsProperty(); | 974 Property* prop = expr->target()->AsProperty(); |
1001 ASSERT(prop != NULL); | 975 ASSERT(prop != NULL); |
1002 ASSERT(prop->key()->AsLiteral() != NULL); | 976 ASSERT(prop->key()->AsLiteral() != NULL); |
1003 | 977 |
(...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1793 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 1767 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
1794 __ mov(Operand(esp, 0), edx); | 1768 __ mov(Operand(esp, 0), edx); |
1795 // And return. | 1769 // And return. |
1796 __ ret(0); | 1770 __ ret(0); |
1797 } | 1771 } |
1798 | 1772 |
1799 | 1773 |
1800 #undef __ | 1774 #undef __ |
1801 | 1775 |
1802 } } // namespace v8::internal | 1776 } } // namespace v8::internal |
OLD | NEW |