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

Side by Side Diff: src/arm/codegen-arm.cc

Issue 536029: Fix a problem with const initialization in the top-level 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/arm/codegen-arm.h ('k') | src/compiler.cc » ('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 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698