| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-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 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); | 256 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); |
| 257 frame_->CallStub(&stub, 3); | 257 frame_->CallStub(&stub, 3); |
| 258 frame_->EmitPush(r0); | 258 frame_->EmitPush(r0); |
| 259 arguments_ref.SetValue(NOT_CONST_INIT); | 259 arguments_ref.SetValue(NOT_CONST_INIT); |
| 260 } | 260 } |
| 261 shadow_ref.SetValue(NOT_CONST_INIT); | 261 shadow_ref.SetValue(NOT_CONST_INIT); |
| 262 } | 262 } |
| 263 frame_->Drop(); // Value is no longer needed. | 263 frame_->Drop(); // Value is no longer needed. |
| 264 } | 264 } |
| 265 | 265 |
| 266 // Initialize ThisFunction reference if present. |
| 267 if (scope_->is_function_scope() && scope_->function() != NULL) { |
| 268 __ mov(ip, Operand(Factory::the_hole_value())); |
| 269 frame_->EmitPush(ip); |
| 270 StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT); |
| 271 } |
| 272 |
| 266 // Generate code to 'execute' declarations and initialize functions | 273 // Generate code to 'execute' declarations and initialize functions |
| 267 // (source elements). In case of an illegal redeclaration we need to | 274 // (source elements). In case of an illegal redeclaration we need to |
| 268 // handle that instead of processing the declarations. | 275 // handle that instead of processing the declarations. |
| 269 if (scope_->HasIllegalRedeclaration()) { | 276 if (scope_->HasIllegalRedeclaration()) { |
| 270 Comment cmnt(masm_, "[ illegal redeclarations"); | 277 Comment cmnt(masm_, "[ illegal redeclarations"); |
| 271 scope_->VisitIllegalRedeclaration(this); | 278 scope_->VisitIllegalRedeclaration(this); |
| 272 } else { | 279 } else { |
| 273 Comment cmnt(masm_, "[ declarations"); | 280 Comment cmnt(masm_, "[ declarations"); |
| 274 ProcessDeclarations(scope_->declarations()); | 281 ProcessDeclarations(scope_->declarations()); |
| 275 // Bail out if a stack-overflow exception occurred when processing | 282 // Bail out if a stack-overflow exception occurred when processing |
| (...skipping 2163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2439 frame_->EmitPop(r0); | 2446 frame_->EmitPop(r0); |
| 2440 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2447 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 2441 __ cmp(r0, ip); | 2448 __ cmp(r0, ip); |
| 2442 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 2449 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 2443 frame_->EmitPush(r0); | 2450 frame_->EmitPush(r0); |
| 2444 } | 2451 } |
| 2445 } | 2452 } |
| 2446 } | 2453 } |
| 2447 | 2454 |
| 2448 | 2455 |
| 2456 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { |
| 2457 ASSERT(slot != NULL); |
| 2458 if (slot->type() == Slot::LOOKUP) { |
| 2459 ASSERT(slot->var()->is_dynamic()); |
| 2460 |
| 2461 // For now, just do a runtime call. |
| 2462 frame_->EmitPush(cp); |
| 2463 __ mov(r0, Operand(slot->var()->name())); |
| 2464 frame_->EmitPush(r0); |
| 2465 |
| 2466 if (init_state == CONST_INIT) { |
| 2467 // Same as the case for a normal store, but ignores attribute |
| 2468 // (e.g. READ_ONLY) of context slot so that we can initialize |
| 2469 // const properties (introduced via eval("const foo = (some |
| 2470 // expr);")). Also, uses the current function context instead of |
| 2471 // the top context. |
| 2472 // |
| 2473 // Note that we must declare the foo upon entry of eval(), via a |
| 2474 // context slot declaration, but we cannot initialize it at the |
| 2475 // same time, because the const declaration may be at the end of |
| 2476 // the eval code (sigh...) and the const variable may have been |
| 2477 // used before (where its value is 'undefined'). Thus, we can only |
| 2478 // do the initialization when we actually encounter the expression |
| 2479 // and when the expression operands are defined and valid, and |
| 2480 // thus we need the split into 2 operations: declaration of the |
| 2481 // context slot followed by initialization. |
| 2482 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 2483 } else { |
| 2484 frame_->CallRuntime(Runtime::kStoreContextSlot, 3); |
| 2485 } |
| 2486 // Storing a variable must keep the (new) value on the expression |
| 2487 // stack. This is necessary for compiling assignment expressions. |
| 2488 frame_->EmitPush(r0); |
| 2489 |
| 2490 } else { |
| 2491 ASSERT(!slot->var()->is_dynamic()); |
| 2492 |
| 2493 JumpTarget exit; |
| 2494 if (init_state == CONST_INIT) { |
| 2495 ASSERT(slot->var()->mode() == Variable::CONST); |
| 2496 // Only the first const initialization must be executed (the slot |
| 2497 // still contains 'the hole' value). When the assignment is |
| 2498 // executed, the code is identical to a normal store (see below). |
| 2499 Comment cmnt(masm_, "[ Init const"); |
| 2500 __ ldr(r2, SlotOperand(slot, r2)); |
| 2501 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 2502 __ cmp(r2, ip); |
| 2503 exit.Branch(ne); |
| 2504 } |
| 2505 |
| 2506 // We must execute the store. Storing a variable must keep the |
| 2507 // (new) value on the stack. This is necessary for compiling |
| 2508 // assignment expressions. |
| 2509 // |
| 2510 // Note: We will reach here even with slot->var()->mode() == |
| 2511 // Variable::CONST because of const declarations which will |
| 2512 // initialize consts to 'the hole' value and by doing so, end up |
| 2513 // calling this code. r2 may be loaded with context; used below in |
| 2514 // RecordWrite. |
| 2515 frame_->EmitPop(r0); |
| 2516 __ str(r0, SlotOperand(slot, r2)); |
| 2517 frame_->EmitPush(r0); |
| 2518 if (slot->type() == Slot::CONTEXT) { |
| 2519 // Skip write barrier if the written value is a smi. |
| 2520 __ tst(r0, Operand(kSmiTagMask)); |
| 2521 exit.Branch(eq); |
| 2522 // r2 is loaded with context when calling SlotOperand above. |
| 2523 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 2524 __ mov(r3, Operand(offset)); |
| 2525 __ RecordWrite(r2, r3, r1); |
| 2526 } |
| 2527 // If we definitely did not jump over the assignment, we do not need |
| 2528 // to bind the exit label. Doing so can defeat peephole |
| 2529 // optimization. |
| 2530 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { |
| 2531 exit.Bind(); |
| 2532 } |
| 2533 } |
| 2534 } |
| 2535 |
| 2536 |
| 2449 void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot, | 2537 void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot, |
| 2450 TypeofState typeof_state, | 2538 TypeofState typeof_state, |
| 2451 Register tmp, | 2539 Register tmp, |
| 2452 Register tmp2, | 2540 Register tmp2, |
| 2453 JumpTarget* slow) { | 2541 JumpTarget* slow) { |
| 2454 // Check that no extension objects have been created by calls to | 2542 // Check that no extension objects have been created by calls to |
| 2455 // eval from the current scope to the global scope. | 2543 // eval from the current scope to the global scope. |
| 2456 Register context = cp; | 2544 Register context = cp; |
| 2457 Scope* s = scope(); | 2545 Scope* s = scope(); |
| 2458 while (s != NULL) { | 2546 while (s != NULL) { |
| (...skipping 1796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4255 VirtualFrame* frame = cgen_->frame(); | 4343 VirtualFrame* frame = cgen_->frame(); |
| 4256 Property* property = expression_->AsProperty(); | 4344 Property* property = expression_->AsProperty(); |
| 4257 if (property != NULL) { | 4345 if (property != NULL) { |
| 4258 cgen_->CodeForSourcePosition(property->position()); | 4346 cgen_->CodeForSourcePosition(property->position()); |
| 4259 } | 4347 } |
| 4260 | 4348 |
| 4261 switch (type_) { | 4349 switch (type_) { |
| 4262 case SLOT: { | 4350 case SLOT: { |
| 4263 Comment cmnt(masm, "[ Store to Slot"); | 4351 Comment cmnt(masm, "[ Store to Slot"); |
| 4264 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 4352 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| 4265 ASSERT(slot != NULL); | 4353 cgen_->StoreToSlot(slot, init_state); |
| 4266 if (slot->type() == Slot::LOOKUP) { | |
| 4267 ASSERT(slot->var()->is_dynamic()); | |
| 4268 | |
| 4269 // For now, just do a runtime call. | |
| 4270 frame->EmitPush(cp); | |
| 4271 __ mov(r0, Operand(slot->var()->name())); | |
| 4272 frame->EmitPush(r0); | |
| 4273 | |
| 4274 if (init_state == CONST_INIT) { | |
| 4275 // Same as the case for a normal store, but ignores attribute | |
| 4276 // (e.g. READ_ONLY) of context slot so that we can initialize | |
| 4277 // const properties (introduced via eval("const foo = (some | |
| 4278 // expr);")). Also, uses the current function context instead of | |
| 4279 // the top context. | |
| 4280 // | |
| 4281 // Note that we must declare the foo upon entry of eval(), via a | |
| 4282 // context slot declaration, but we cannot initialize it at the | |
| 4283 // same time, because the const declaration may be at the end of | |
| 4284 // the eval code (sigh...) and the const variable may have been | |
| 4285 // used before (where its value is 'undefined'). Thus, we can only | |
| 4286 // do the initialization when we actually encounter the expression | |
| 4287 // and when the expression operands are defined and valid, and | |
| 4288 // thus we need the split into 2 operations: declaration of the | |
| 4289 // context slot followed by initialization. | |
| 4290 frame->CallRuntime(Runtime::kInitializeConstContextSlot, 3); | |
| 4291 } else { | |
| 4292 frame->CallRuntime(Runtime::kStoreContextSlot, 3); | |
| 4293 } | |
| 4294 // Storing a variable must keep the (new) value on the expression | |
| 4295 // stack. This is necessary for compiling assignment expressions. | |
| 4296 frame->EmitPush(r0); | |
| 4297 | |
| 4298 } else { | |
| 4299 ASSERT(!slot->var()->is_dynamic()); | |
| 4300 | |
| 4301 JumpTarget exit; | |
| 4302 if (init_state == CONST_INIT) { | |
| 4303 ASSERT(slot->var()->mode() == Variable::CONST); | |
| 4304 // Only the first const initialization must be executed (the slot | |
| 4305 // still contains 'the hole' value). When the assignment is | |
| 4306 // executed, the code is identical to a normal store (see below). | |
| 4307 Comment cmnt(masm, "[ Init const"); | |
| 4308 __ ldr(r2, cgen_->SlotOperand(slot, r2)); | |
| 4309 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
| 4310 __ cmp(r2, ip); | |
| 4311 exit.Branch(ne); | |
| 4312 } | |
| 4313 | |
| 4314 // We must execute the store. Storing a variable must keep the | |
| 4315 // (new) value on the stack. This is necessary for compiling | |
| 4316 // assignment expressions. | |
| 4317 // | |
| 4318 // Note: We will reach here even with slot->var()->mode() == | |
| 4319 // Variable::CONST because of const declarations which will | |
| 4320 // initialize consts to 'the hole' value and by doing so, end up | |
| 4321 // calling this code. r2 may be loaded with context; used below in | |
| 4322 // RecordWrite. | |
| 4323 frame->EmitPop(r0); | |
| 4324 __ str(r0, cgen_->SlotOperand(slot, r2)); | |
| 4325 frame->EmitPush(r0); | |
| 4326 if (slot->type() == Slot::CONTEXT) { | |
| 4327 // Skip write barrier if the written value is a smi. | |
| 4328 __ tst(r0, Operand(kSmiTagMask)); | |
| 4329 exit.Branch(eq); | |
| 4330 // r2 is loaded with context when calling SlotOperand above. | |
| 4331 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | |
| 4332 __ mov(r3, Operand(offset)); | |
| 4333 __ RecordWrite(r2, r3, r1); | |
| 4334 } | |
| 4335 // If we definitely did not jump over the assignment, we do not need | |
| 4336 // to bind the exit label. Doing so can defeat peephole | |
| 4337 // optimization. | |
| 4338 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { | |
| 4339 exit.Bind(); | |
| 4340 } | |
| 4341 } | |
| 4342 break; | 4354 break; |
| 4343 } | 4355 } |
| 4344 | 4356 |
| 4345 case NAMED: { | 4357 case NAMED: { |
| 4346 Comment cmnt(masm, "[ Store to named Property"); | 4358 Comment cmnt(masm, "[ Store to named Property"); |
| 4347 // Call the appropriate IC code. | 4359 // Call the appropriate IC code. |
| 4348 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 4360 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 4349 Handle<String> name(GetName()); | 4361 Handle<String> name(GetName()); |
| 4350 | 4362 |
| 4351 Result value(r0); | 4363 Result value(r0); |
| (...skipping 2262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6614 ASSERT((static_cast<unsigned>(cc_) >> 26) < (1 << 16)); | 6626 ASSERT((static_cast<unsigned>(cc_) >> 26) < (1 << 16)); |
| 6615 int nnn_value = (never_nan_nan_ ? 2 : 0); | 6627 int nnn_value = (never_nan_nan_ ? 2 : 0); |
| 6616 if (cc_ != eq) nnn_value = 0; // Avoid duplicate stubs. | 6628 if (cc_ != eq) nnn_value = 0; // Avoid duplicate stubs. |
| 6617 return (static_cast<unsigned>(cc_) >> 26) | nnn_value | (strict_ ? 1 : 0); | 6629 return (static_cast<unsigned>(cc_) >> 26) | nnn_value | (strict_ ? 1 : 0); |
| 6618 } | 6630 } |
| 6619 | 6631 |
| 6620 | 6632 |
| 6621 #undef __ | 6633 #undef __ |
| 6622 | 6634 |
| 6623 } } // namespace v8::internal | 6635 } } // namespace v8::internal |
| OLD | NEW |