| OLD | NEW | 
|     1 // Copyright 2012 the V8 project authors. All rights reserved. |     1 // Copyright 2012 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 248 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   259   if (scope()->HasIllegalRedeclaration()) { |   259   if (scope()->HasIllegalRedeclaration()) { | 
|   260     Comment cmnt(masm_, "[ Declarations"); |   260     Comment cmnt(masm_, "[ Declarations"); | 
|   261     scope()->VisitIllegalRedeclaration(this); |   261     scope()->VisitIllegalRedeclaration(this); | 
|   262  |   262  | 
|   263   } else { |   263   } else { | 
|   264     PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); |   264     PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); | 
|   265     { Comment cmnt(masm_, "[ Declarations"); |   265     { Comment cmnt(masm_, "[ Declarations"); | 
|   266       // For named function expressions, declare the function name as a |   266       // For named function expressions, declare the function name as a | 
|   267       // constant. |   267       // constant. | 
|   268       if (scope()->is_function_scope() && scope()->function() != NULL) { |   268       if (scope()->is_function_scope() && scope()->function() != NULL) { | 
|   269         VariableProxy* proxy = scope()->function(); |   269         VariableDeclaration* function = scope()->function(); | 
|   270         ASSERT(proxy->var()->mode() == CONST || |   270         ASSERT(function->proxy()->var()->mode() == CONST || | 
|   271                proxy->var()->mode() == CONST_HARMONY); |   271                function->proxy()->var()->mode() == CONST_HARMONY); | 
|   272         ASSERT(proxy->var()->location() != Variable::UNALLOCATED); |   272         ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); | 
|   273         EmitDeclaration(proxy, proxy->var()->mode(), NULL); |   273         VisitVariableDeclaration(function); | 
|   274       } |   274       } | 
|   275       VisitDeclarations(scope()->declarations()); |   275       VisitDeclarations(scope()->declarations()); | 
|   276     } |   276     } | 
|   277  |   277  | 
|   278     { Comment cmnt(masm_, "[ Stack check"); |   278     { Comment cmnt(masm_, "[ Stack check"); | 
|   279       PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); |   279       PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); | 
|   280       Label ok; |   280       Label ok; | 
|   281       ExternalReference stack_limit = |   281       ExternalReference stack_limit = | 
|   282           ExternalReference::address_of_stack_limit(isolate()); |   282           ExternalReference::address_of_stack_limit(isolate()); | 
|   283       __ cmp(esp, Operand::StaticVariable(stack_limit)); |   283       __ cmp(esp, Operand::StaticVariable(stack_limit)); | 
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   743   if (should_normalize) __ jmp(&skip, Label::kNear); |   743   if (should_normalize) __ jmp(&skip, Label::kNear); | 
|   744   PrepareForBailout(expr, TOS_REG); |   744   PrepareForBailout(expr, TOS_REG); | 
|   745   if (should_normalize) { |   745   if (should_normalize) { | 
|   746     __ cmp(eax, isolate()->factory()->true_value()); |   746     __ cmp(eax, isolate()->factory()->true_value()); | 
|   747     Split(equal, if_true, if_false, NULL); |   747     Split(equal, if_true, if_false, NULL); | 
|   748     __ bind(&skip); |   748     __ bind(&skip); | 
|   749   } |   749   } | 
|   750 } |   750 } | 
|   751  |   751  | 
|   752  |   752  | 
|   753 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, |   753 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { | 
|   754                                         VariableMode mode, |   754   // The variable in the declaration always resides in the current function | 
|   755                                         FunctionLiteral* function) { |   755   // context. | 
 |   756   ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 
 |   757   if (FLAG_debug_code) { | 
 |   758     // Check that we're not inside a with or catch context. | 
 |   759     __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); | 
 |   760     __ cmp(ebx, isolate()->factory()->with_context_map()); | 
 |   761     __ Check(not_equal, "Declaration in with context."); | 
 |   762     __ cmp(ebx, isolate()->factory()->catch_context_map()); | 
 |   763     __ Check(not_equal, "Declaration in catch context."); | 
 |   764   } | 
 |   765 } | 
 |   766  | 
 |   767  | 
 |   768 void FullCodeGenerator::VisitVariableDeclaration( | 
 |   769     VariableDeclaration* declaration) { | 
|   756   // If it was not possible to allocate the variable at compile time, we |   770   // If it was not possible to allocate the variable at compile time, we | 
|   757   // need to "declare" it at runtime to make sure it actually exists in the |   771   // need to "declare" it at runtime to make sure it actually exists in the | 
|   758   // local context. |   772   // local context. | 
 |   773   VariableProxy* proxy = declaration->proxy(); | 
 |   774   VariableMode mode = declaration->mode(); | 
|   759   Variable* variable = proxy->var(); |   775   Variable* variable = proxy->var(); | 
|   760   bool binding_needs_init = (function == NULL) && |   776   bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 
|   761       (mode == CONST || mode == CONST_HARMONY || mode == LET); |  | 
|   762   switch (variable->location()) { |   777   switch (variable->location()) { | 
|   763     case Variable::UNALLOCATED: |   778     case Variable::UNALLOCATED: | 
|   764       ++global_count_; |   779       ++global_count_; | 
|   765       break; |   780       break; | 
|   766  |   781  | 
|   767     case Variable::PARAMETER: |   782     case Variable::PARAMETER: | 
|   768     case Variable::LOCAL: |   783     case Variable::LOCAL: | 
|   769       if (function != NULL) { |   784       if (hole_init) { | 
|   770         Comment cmnt(masm_, "[ Declaration"); |   785         Comment cmnt(masm_, "[ VariableDeclaration"); | 
|   771         VisitForAccumulatorValue(function); |  | 
|   772         __ mov(StackOperand(variable), result_register()); |  | 
|   773       } else if (binding_needs_init) { |  | 
|   774         Comment cmnt(masm_, "[ Declaration"); |  | 
|   775         __ mov(StackOperand(variable), |   786         __ mov(StackOperand(variable), | 
|   776                Immediate(isolate()->factory()->the_hole_value())); |   787                Immediate(isolate()->factory()->the_hole_value())); | 
|   777       } |   788       } | 
|   778       break; |   789       break; | 
|   779  |   790  | 
|   780     case Variable::CONTEXT: |   791     case Variable::CONTEXT: | 
|   781       // The variable in the decl always resides in the current function |   792       if (hole_init) { | 
|   782       // context. |   793         Comment cmnt(masm_, "[ VariableDeclaration"); | 
|   783       ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); |   794         EmitDebugCheckDeclarationContext(variable); | 
|   784       if (FLAG_debug_code) { |  | 
|   785         // Check that we're not inside a with or catch context. |  | 
|   786         __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); |  | 
|   787         __ cmp(ebx, isolate()->factory()->with_context_map()); |  | 
|   788         __ Check(not_equal, "Declaration in with context."); |  | 
|   789         __ cmp(ebx, isolate()->factory()->catch_context_map()); |  | 
|   790         __ Check(not_equal, "Declaration in catch context."); |  | 
|   791       } |  | 
|   792       if (function != NULL) { |  | 
|   793         Comment cmnt(masm_, "[ Declaration"); |  | 
|   794         VisitForAccumulatorValue(function); |  | 
|   795         __ mov(ContextOperand(esi, variable->index()), result_register()); |  | 
|   796         // We know that we have written a function, which is not a smi. |  | 
|   797         __ RecordWriteContextSlot(esi, |  | 
|   798                                   Context::SlotOffset(variable->index()), |  | 
|   799                                   result_register(), |  | 
|   800                                   ecx, |  | 
|   801                                   kDontSaveFPRegs, |  | 
|   802                                   EMIT_REMEMBERED_SET, |  | 
|   803                                   OMIT_SMI_CHECK); |  | 
|   804         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |  | 
|   805       } else if (binding_needs_init) { |  | 
|   806         Comment cmnt(masm_, "[ Declaration"); |  | 
|   807         __ mov(ContextOperand(esi, variable->index()), |   795         __ mov(ContextOperand(esi, variable->index()), | 
|   808                Immediate(isolate()->factory()->the_hole_value())); |   796                Immediate(isolate()->factory()->the_hole_value())); | 
|   809         // No write barrier since the hole value is in old space. |   797         // No write barrier since the hole value is in old space. | 
|   810         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |   798         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 
|   811       } |   799       } | 
|   812       break; |   800       break; | 
|   813  |   801  | 
|   814     case Variable::LOOKUP: { |   802     case Variable::LOOKUP: { | 
|   815       Comment cmnt(masm_, "[ Declaration"); |   803       Comment cmnt(masm_, "[ VariableDeclaration"); | 
|   816       __ push(esi); |   804       __ push(esi); | 
|   817       __ push(Immediate(variable->name())); |   805       __ push(Immediate(variable->name())); | 
|   818       // Declaration nodes are always introduced in one of four modes. |   806       // VariableDeclaration nodes are always introduced in one of four modes. | 
|   819       ASSERT(mode == VAR || |   807       ASSERT(mode == VAR || mode == LET || | 
|   820              mode == CONST || |   808              mode == CONST || mode == CONST_HARMONY); | 
|   821              mode == CONST_HARMONY || |  | 
|   822              mode == LET); |  | 
|   823       PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) |   809       PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) | 
|   824           ? READ_ONLY : NONE; |   810           ? READ_ONLY : NONE; | 
|   825       __ push(Immediate(Smi::FromInt(attr))); |   811       __ push(Immediate(Smi::FromInt(attr))); | 
|   826       // Push initial value, if any. |   812       // Push initial value, if any. | 
|   827       // Note: For variables we must not push an initial value (such as |   813       // Note: For variables we must not push an initial value (such as | 
|   828       // 'undefined') because we may have a (legal) redeclaration and we |   814       // 'undefined') because we may have a (legal) redeclaration and we | 
|   829       // must not destroy the current value. |   815       // must not destroy the current value. | 
|   830       if (function != NULL) { |   816       if (hole_init) { | 
|   831         VisitForStackValue(function); |  | 
|   832       } else if (binding_needs_init) { |  | 
|   833         __ push(Immediate(isolate()->factory()->the_hole_value())); |   817         __ push(Immediate(isolate()->factory()->the_hole_value())); | 
|   834       } else { |   818       } else { | 
|   835         __ push(Immediate(Smi::FromInt(0)));  // Indicates no initial value. |   819         __ push(Immediate(Smi::FromInt(0)));  // Indicates no initial value. | 
|   836       } |   820       } | 
|   837       __ CallRuntime(Runtime::kDeclareContextSlot, 4); |   821       __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 
|   838       break; |   822       break; | 
|   839     } |   823     } | 
|   840   } |   824   } | 
|   841 } |   825 } | 
|   842  |   826  | 
|   843  |   827  | 
 |   828 void FullCodeGenerator::VisitFunctionDeclaration( | 
 |   829     FunctionDeclaration* declaration) { | 
 |   830   VariableProxy* proxy = declaration->proxy(); | 
 |   831   Variable* variable = proxy->var(); | 
 |   832   switch (variable->location()) { | 
 |   833     case Variable::UNALLOCATED: | 
 |   834       ++global_count_; | 
 |   835       break; | 
 |   836  | 
 |   837     case Variable::PARAMETER: | 
 |   838     case Variable::LOCAL: { | 
 |   839       Comment cmnt(masm_, "[ FunctionDeclaration"); | 
 |   840       VisitForAccumulatorValue(declaration->fun()); | 
 |   841       __ mov(StackOperand(variable), result_register()); | 
 |   842       break; | 
 |   843     } | 
 |   844  | 
 |   845     case Variable::CONTEXT: { | 
 |   846       Comment cmnt(masm_, "[ FunctionDeclaration"); | 
 |   847       EmitDebugCheckDeclarationContext(variable); | 
 |   848       VisitForAccumulatorValue(declaration->fun()); | 
 |   849       __ mov(ContextOperand(esi, variable->index()), result_register()); | 
 |   850       // We know that we have written a function, which is not a smi. | 
 |   851       __ RecordWriteContextSlot(esi, | 
 |   852                                 Context::SlotOffset(variable->index()), | 
 |   853                                 result_register(), | 
 |   854                                 ecx, | 
 |   855                                 kDontSaveFPRegs, | 
 |   856                                 EMIT_REMEMBERED_SET, | 
 |   857                                 OMIT_SMI_CHECK); | 
 |   858       PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 
 |   859       break; | 
 |   860     } | 
 |   861  | 
 |   862     case Variable::LOOKUP: { | 
 |   863       Comment cmnt(masm_, "[ FunctionDeclaration"); | 
 |   864       __ push(esi); | 
 |   865       __ push(Immediate(variable->name())); | 
 |   866       __ push(Immediate(Smi::FromInt(NONE))); | 
 |   867       VisitForStackValue(declaration->fun()); | 
 |   868       __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 
 |   869       break; | 
 |   870     } | 
 |   871   } | 
 |   872 } | 
 |   873  | 
 |   874  | 
 |   875 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 
 |   876   VariableProxy* proxy = declaration->proxy(); | 
 |   877   Variable* variable = proxy->var(); | 
 |   878   switch (variable->location()) { | 
 |   879     case Variable::UNALLOCATED: | 
 |   880       ++global_count_; | 
 |   881       break; | 
 |   882  | 
 |   883     case Variable::CONTEXT: { | 
 |   884       Comment cmnt(masm_, "[ ModuleDeclaration"); | 
 |   885       EmitDebugCheckDeclarationContext(variable); | 
 |   886       // TODO(rossberg): initialize module instance object | 
 |   887       break; | 
 |   888     } | 
 |   889  | 
 |   890     case Variable::PARAMETER: | 
 |   891     case Variable::LOCAL: | 
 |   892     case Variable::LOOKUP: | 
 |   893       UNREACHABLE(); | 
 |   894   } | 
 |   895 } | 
 |   896  | 
 |   897  | 
 |   898 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { | 
 |   899   VariableProxy* proxy = declaration->proxy(); | 
 |   900   Variable* variable = proxy->var(); | 
 |   901   switch (variable->location()) { | 
 |   902     case Variable::UNALLOCATED: | 
 |   903       ++global_count_; | 
 |   904       break; | 
 |   905  | 
 |   906     case Variable::CONTEXT: { | 
 |   907       Comment cmnt(masm_, "[ ImportDeclaration"); | 
 |   908       EmitDebugCheckDeclarationContext(variable); | 
 |   909       // TODO(rossberg) | 
 |   910       break; | 
 |   911     } | 
 |   912  | 
 |   913     case Variable::PARAMETER: | 
 |   914     case Variable::LOCAL: | 
 |   915     case Variable::LOOKUP: | 
 |   916       UNREACHABLE(); | 
 |   917   } | 
 |   918 } | 
 |   919  | 
 |   920  | 
 |   921 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { | 
 |   922   // TODO(rossberg) | 
 |   923 } | 
 |   924  | 
 |   925  | 
|   844 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |   926 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 
|   845   // Call the runtime to declare the globals. |   927   // Call the runtime to declare the globals. | 
|   846   __ push(esi);  // The context is the first argument. |   928   __ push(esi);  // The context is the first argument. | 
|   847   __ push(Immediate(pairs)); |   929   __ push(Immediate(pairs)); | 
|   848   __ push(Immediate(Smi::FromInt(DeclareGlobalsFlags()))); |   930   __ push(Immediate(Smi::FromInt(DeclareGlobalsFlags()))); | 
|   849   __ CallRuntime(Runtime::kDeclareGlobals, 3); |   931   __ CallRuntime(Runtime::kDeclareGlobals, 3); | 
|   850   // Return value is ignored. |   932   // Return value is ignored. | 
|   851 } |   933 } | 
|   852  |   934  | 
|   853  |   935  | 
| (...skipping 3626 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  4480   *context_length = 0; |  4562   *context_length = 0; | 
|  4481   return previous_; |  4563   return previous_; | 
|  4482 } |  4564 } | 
|  4483  |  4565  | 
|  4484  |  4566  | 
|  4485 #undef __ |  4567 #undef __ | 
|  4486  |  4568  | 
|  4487 } }  // namespace v8::internal |  4569 } }  // namespace v8::internal | 
|  4488  |  4570  | 
|  4489 #endif  // V8_TARGET_ARCH_IA32 |  4571 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW |