!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
+ FastNewClosureStub stub(info->strict_mode_flag());
__ mov(r0, Operand(info));
__ push(r0);
__ CallStub(&stub);
LOperand* object() { return inputs_[0]; }
LOperand* value() { return inputs_[1]; }
Handle<Object> name() const { return hydrogen()->name(); }
- bool strict_mode() { return hydrogen()->strict_mode(); }
+ StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ bool strict_mode() { return strict_mode_flag() == kStrictMode; }
};
Handle<SharedFunctionInfo> shared_info = instr->shared_info();
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && shared_info->num_literals() == 0) {
- FastNewClosureStub stub(
- shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
+ FastNewClosureStub stub(shared_info->strict_mode_flag());
__ mov(r1, Operand(shared_info));
__ push(r1);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
bool is_done() const { return status_ == DONE; }
bool is_aborted() const { return status_ == ABORTED; }
- int strict_mode_flag() const {
- return info()->is_strict_mode() ? kStrictMode : kNonStrictMode;
+ StrictModeFlag strict_mode_flag() const {
+ return info()->strict_mode_flag();
}
LChunk* chunk() const { return chunk_; }
}
-bool FunctionLiteral::strict_mode() const {
- return scope()->is_strict_mode();
+StrictModeFlag FunctionLiteral::strict_mode_flag() const {
+ return scope()->strict_mode_flag();
}
int end_position() const;
bool is_expression() const { return is_expression_; }
bool is_anonymous() const { return is_anonymous_; }
- bool strict_mode() const;
+ bool strict_mode() const { return strict_mode_flag() == kStrictMode; }
+ StrictModeFlag strict_mode_flag() const;
int materialized_literal_count() { return materialized_literal_count_; }
int expected_property_count() { return expected_property_count_; }
CompilationInfo info(script);
info.MarkAsEval();
if (is_global) info.MarkAsGlobal();
- if (strict_mode == kStrictMode) info.MarkAsStrictMode();
+ info.SetStrictModeFlag(strict_mode);
info.SetCallingContext(context);
result = MakeFunctionInfo(&info);
if (!result.is_null()) {
// If caller is strict mode, the result must be strict as well,
// but not the other way around. Consider:
// eval("'use strict'; ...");
+ // TODO(keuchel): adapt this for extended mode.
ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
compilation_cache->PutEval(source, context, is_global, result);
}
HistogramTimerScope timer(isolate->counters()->compile_lazy());
// After parsing we know function's strict mode. Remember it.
- if (info->function()->strict_mode()) {
- shared->set_strict_mode(true);
- info->MarkAsStrictMode();
- }
+ StrictModeFlag strict_mode = info->function()->strict_mode_flag();
+ ASSERT(info->strict_mode_flag() == kNonStrictMode ||
+ info->strict_mode_flag() == strict_mode);
+ ASSERT(shared->strict_mode_flag() == kNonStrictMode ||
+ shared->strict_mode_flag() == strict_mode);
+ info->SetStrictModeFlag(strict_mode);
+ shared->set_strict_mode_flag(strict_mode);
// Compile the code.
if (!MakeCode(info)) {
CompilationInfo info(script);
info.SetFunction(literal);
info.SetScope(literal->scope());
- if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode();
+ info.SetStrictModeFlag(literal->scope()->strict_mode_flag());
LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
// Determine if the function can be lazily compiled. This is necessary to
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
- function_info->set_strict_mode(lit->strict_mode());
+ function_info->set_strict_mode_flag(lit->strict_mode_flag());
function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
}
bool is_lazy() const { return IsLazy::decode(flags_); }
bool is_eval() const { return IsEval::decode(flags_); }
bool is_global() const { return IsGlobal::decode(flags_); }
- bool is_strict_mode() const { return IsStrictMode::decode(flags_); }
+ bool is_strict_mode() const { return strict_mode_flag() == kStrictMode; }
+ StrictModeFlag strict_mode_flag() const {
+ return StrictModeFlagField::decode(flags_);
+ }
bool is_in_loop() const { return IsInLoop::decode(flags_); }
FunctionLiteral* function() const { return function_; }
Scope* scope() const { return scope_; }
ASSERT(!is_lazy());
flags_ |= IsGlobal::encode(true);
}
- void MarkAsStrictMode() {
- flags_ |= IsStrictMode::encode(true);
- }
- StrictModeFlag StrictMode() {
- return is_strict_mode() ? kStrictMode : kNonStrictMode;
+ void SetStrictModeFlag(StrictModeFlag strict_mode_flag) {
+ ASSERT(StrictModeFlagField::decode(flags_) == kNonStrictMode ||
+ StrictModeFlagField::decode(flags_) == strict_mode_flag);
+ flags_ = StrictModeFlagField::update(flags_, strict_mode_flag);
}
void MarkAsInLoop() {
ASSERT(is_lazy());
if (script_->type()->value() == Script::TYPE_NATIVE) {
MarkAsNative();
}
- if (!shared_info_.is_null() && shared_info_->strict_mode()) {
- MarkAsStrictMode();
+ if (!shared_info_.is_null()) {
+ ASSERT(strict_mode_flag() == kNonStrictMode);
+ SetStrictModeFlag(shared_info_->strict_mode_flag());
}
}
// Flags that can be set for lazy compilation.
class IsInLoop: public BitField<bool, 3, 1> {};
// Strict mode - used in eager compilation.
- class IsStrictMode: public BitField<bool, 4, 1> {};
+ class StrictModeFlagField: public BitField<StrictModeFlag, 4, 1> {};
// Is this a function from our natives.
class IsNative: public BitField<bool, 6, 1> {};
// Is this code being compiled with support for deoptimization..
int FullCodeGenerator::DeclareGlobalsFlags() {
- int flags = 0;
- if (is_eval()) flags |= kDeclareGlobalsEvalFlag;
- if (is_strict_mode()) flags |= kDeclareGlobalsStrictModeFlag;
- if (is_native()) flags |= kDeclareGlobalsNativeFlag;
- return flags;
+ ASSERT(DeclareGlobalsStrictModeFlag::is_valid(strict_mode_flag()));
+ return DeclareGlobalsEvalFlag::encode(is_eval()) |
+ DeclareGlobalsStrictModeFlag::encode(strict_mode_flag()) |
+ DeclareGlobalsNativeFlag::encode(is_native());
}
Handle<Script> script() { return info_->script(); }
bool is_eval() { return info_->is_eval(); }
bool is_native() { return info_->is_native(); }
- bool is_strict_mode() { return function()->strict_mode(); }
+ bool is_strict_mode() {
+ return strict_mode_flag() == kStrictMode;
+ }
StrictModeFlag strict_mode_flag() {
- return is_strict_mode() ? kStrictMode : kNonStrictMode;
+ return function()->strict_mode_flag();
}
FunctionLiteral* function() { return info_->function(); }
Scope* scope() { return scope_; }
HValue* object,
Handle<String> name,
HValue* value,
- bool strict_mode)
+ StrictModeFlag strict_mode_flag)
: name_(name),
- strict_mode_(strict_mode) {
+ strict_mode_flag_(strict_mode_flag) {
SetOperandAt(0, object);
SetOperandAt(1, value);
SetOperandAt(2, context);
HValue* value() { return OperandAt(1); }
HValue* context() { return OperandAt(2); }
Handle<String> name() { return name_; }
- bool strict_mode() { return strict_mode_; }
+ StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
virtual void PrintDataTo(StringStream* stream);
private:
Handle<String> name_;
- bool strict_mode_;
+ StrictModeFlag strict_mode_flag_;
};
literal,
name,
value,
- function_strict_mode());
+ function_strict_mode_flag());
AddInstruction(store);
AddSimulate(key->id());
} else {
object,
name,
value,
- function_strict_mode());
+ function_strict_mode_flag());
}
global_object,
var->name(),
value,
- function_strict_mode());
+ function_strict_mode_flag());
instr->set_position(position);
AddInstruction(instr);
ASSERT(instr->HasSideEffects());
object,
key,
value,
- function_strict_mode());
+ function_strict_mode_flag());
}
bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
void ClearInlinedTestContext() {
function_state()->ClearInlinedTestContext();
}
- bool function_strict_mode() {
- return function_state()->compilation_info()->is_strict_mode();
+ StrictModeFlag function_strict_mode_flag() {
+ return function_state()->compilation_info()->strict_mode_flag();
}
// Generators for inline runtime functions.
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
+ FastNewClosureStub stub(info->strict_mode_flag());
__ push(Immediate(info));
__ CallStub(&stub);
} else {
Handle<SharedFunctionInfo> shared_info = instr->shared_info();
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && shared_info->num_literals() == 0) {
- FastNewClosureStub stub(
- shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
+ FastNewClosureStub stub(shared_info->strict_mode_flag());
__ push(Immediate(shared_info));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
bool is_done() const { return status_ == DONE; }
bool is_aborted() const { return status_ == ABORTED; }
- int strict_mode_flag() const {
- return info()->is_strict_mode() ? kStrictMode : kNonStrictMode;
+ StrictModeFlag strict_mode_flag() const {
+ return info()->strict_mode_flag();
}
bool dynamic_frame_alignment() const { return dynamic_frame_alignment_; }
void set_dynamic_frame_alignment(bool value) {
LOperand* object() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
Handle<Object> name() const { return hydrogen()->name(); }
- bool strict_mode() { return hydrogen()->strict_mode(); }
+ StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ bool strict_mode() { return strict_mode_flag() == kStrictMode; }
};
}
-BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, strict_mode,
- kStrictModeFunction)
+StrictModeFlag SharedFunctionInfo::strict_mode_flag() {
+ return BooleanBit::get(compiler_hints(), kStrictModeFunction)
+ ? kStrictMode : kNonStrictMode;
+}
+
+
+void SharedFunctionInfo::set_strict_mode_flag(StrictModeFlag strict_mode_flag) {
+ ASSERT(strict_mode_flag == kStrictMode ||
+ strict_mode_flag == kNonStrictMode);
+ bool value = strict_mode_flag == kStrictMode;
+ set_compiler_hints(
+ BooleanBit::set(compiler_hints(), kStrictModeFunction, value));
+}
+
+
+BOOL_GETTER(SharedFunctionInfo, compiler_hints, strict_mode,
+ kStrictModeFunction)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
name_should_print_as_anonymous,
SharedFunctionInfo* value) {
StringSharedKey key(src,
context->closure()->shared(),
- value->strict_mode() ? kStrictMode : kNonStrictMode);
+ value->strict_mode_flag());
Object* obj;
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
DECL_BOOLEAN_ACCESSORS(optimization_disabled)
// Indicates whether the function is a strict mode function.
- DECL_BOOLEAN_ACCESSORS(strict_mode)
+ inline bool strict_mode();
+
+ // Indicates the mode of the function.
+ inline StrictModeFlag strict_mode_flag();
+ inline void set_strict_mode_flag(StrictModeFlag strict_mode_flag);
// False if the function definitely does not allocate an arguments object.
DECL_BOOLEAN_ACCESSORS(uses_arguments)
bool in_global_context,
StrictModeFlag strict_mode,
ZoneScope* zone_scope) {
+ ASSERT(top_scope_ == NULL);
ASSERT(target_stack_ == NULL);
if (pre_data_ != NULL) pre_data_->Initialize();
scope->set_start_position(0);
scope->set_end_position(source->length());
LexicalScope lexical_scope(this, scope, isolate());
- if (strict_mode == kStrictMode) {
- top_scope_->EnableStrictMode();
- }
+ ASSERT(top_scope_->strict_mode_flag() == kNonStrictMode);
+ top_scope_->SetStrictModeFlag(strict_mode);
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
bool ok = true;
int beg_loc = scanner().location().beg_pos;
ZoneScope* zone_scope) {
Handle<SharedFunctionInfo> shared_info = info->shared_info();
scanner_.Initialize(source);
+ ASSERT(top_scope_ == NULL);
ASSERT(target_stack_ == NULL);
Handle<String> name(String::cast(shared_info->name()));
scope = Scope::DeserializeScopeChain(info, scope);
}
LexicalScope lexical_scope(this, scope, isolate());
-
- if (shared_info->strict_mode()) {
- top_scope_->EnableStrictMode();
- }
-
+ ASSERT(scope->strict_mode_flag() == kNonStrictMode ||
+ scope->strict_mode_flag() == info->strict_mode_flag());
+ ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag());
+ scope->SetStrictModeFlag(shared_info->strict_mode_flag());
FunctionLiteral::Type type = shared_info->is_expression()
? (shared_info->is_anonymous()
? FunctionLiteral::ANONYMOUS_EXPRESSION
directive->Equals(isolate()->heap()->use_strict()) &&
token_loc.end_pos - token_loc.beg_pos ==
isolate()->heap()->use_strict()->length() + 2) {
- top_scope_->EnableStrictMode();
+ top_scope_->SetStrictModeFlag(kStrictMode);
// "use strict" is the only directive for now.
directive_prologue = false;
}
// Construct block expecting 16 statements.
Block* body = new(zone()) Block(isolate(), labels, 16, false);
Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
- if (top_scope_->is_strict_mode()) {
- block_scope->EnableStrictMode();
- }
// Parse the statements and collect escaping labels.
Expect(Token::LBRACE, CHECK_OK);
} else {
// Add strict mode.
// We may want to pass singleton to avoid Literal allocations.
- StrictModeFlag flag = initialization_scope->is_strict_mode()
- ? kStrictMode
- : kNonStrictMode;
+ StrictModeFlag flag = initialization_scope->strict_mode_flag();
arguments->Add(NewNumberLiteral(flag));
// Be careful not to assign a value to the global variable if
Expect(Token::LPAREN, CHECK_OK);
catch_scope = NewScope(top_scope_, CATCH_SCOPE);
- if (top_scope_->is_strict_mode()) {
- catch_scope->EnableStrictMode();
- }
catch_scope->set_start_position(scanner().location().beg_pos);
name = ParseIdentifier(CHECK_OK);
// Create an in-between scope for let-bound iteration variables.
Scope* saved_scope = top_scope_;
Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE);
- if (top_scope_->is_strict_mode()) {
- for_scope->EnableStrictMode();
- }
top_scope_ = for_scope;
Expect(Token::FOR, CHECK_OK);
scanner().SeekForward(scope->end_position() - 1);
materialized_literal_count = entry.literal_count();
expected_property_count = entry.property_count();
- if (entry.strict_mode()) top_scope_->EnableStrictMode();
+ if (entry.strict_mode()) top_scope_->SetStrictModeFlag(kStrictMode);
only_simple_this_property_assignments = false;
this_property_assignments = isolate()->factory()->empty_fixed_array();
Expect(Token::RBRACE, CHECK_OK);
Handle<String> source = Handle<String>(String::cast(script->source()));
result = parser.ParseProgram(source,
info->is_global(),
- info->StrictMode());
+ info->strict_mode_flag());
}
}
info->SetFunction(result);
typedef int Arguments;
+ // The Strict Mode (ECMA-262 5th edition, 4.2.2).
+ enum StrictModeFlag {
+ kNonStrictMode,
+ kStrictMode,
+ // This value is never used, but is needed to prevent GCC 4.5 from failing
+ // to compile when we assert that a flag is either kNonStrictMode or
+ // kStrictMode.
+ kInvalidStrictFlag
+ };
+
class Scope {
public:
Scope(Scope** variable, ScopeType type)
materialized_literal_count_(0),
expected_properties_(0),
with_nesting_count_(0),
- strict_((prev_ != NULL) && prev_->is_strict()) {
+ strict_mode_flag_((prev_ != NULL) ? prev_->strict_mode_flag()
+ : kNonStrictMode) {
*variable = this;
}
~Scope() { *variable_ = prev_; }
int expected_properties() { return expected_properties_; }
int materialized_literal_count() { return materialized_literal_count_; }
bool IsInsideWith() { return with_nesting_count_ != 0; }
- bool is_strict() { return strict_; }
- void set_strict() { strict_ = true; }
+ bool is_strict_mode() { return strict_mode_flag_ == kStrictMode; }
+ StrictModeFlag strict_mode_flag() {
+ return strict_mode_flag_;
+ }
+ void set_strict_mode_flag(StrictModeFlag strict_mode_flag) {
+ strict_mode_flag_ = strict_mode_flag;
+ }
void EnterWith() { with_nesting_count_++; }
void LeaveWith() { with_nesting_count_--; }
int materialized_literal_count_;
int expected_properties_;
int with_nesting_count_;
- bool strict_;
+ StrictModeFlag strict_mode_flag_;
};
// Private constructor only used in PreParseProgram.
if (stack_overflow_) return kPreParseStackOverflow;
if (!ok) {
ReportUnexpectedToken(scanner_->current_token());
- } else if (scope_->is_strict()) {
+ } else if (scope_->is_strict_mode()) {
CheckOctalLiteral(start_position, scanner_->location().end_pos, &ok);
}
return kPreParseSuccess;
bool peek_any_identifier();
void set_strict_mode() {
- scope_->set_strict();
+ scope_->set_strict_mode_flag(kStrictMode);
}
- bool strict_mode() { return scope_->is_strict(); }
+ bool strict_mode() { return scope_->strict_mode_flag() == kStrictMode; }
void Consume(i::Token::Value token) { Next(); }
// non-deletable. However, neither SpiderMonkey nor KJS creates the
// property as read-only, so we don't either.
int attr = NONE;
- if ((flags & kDeclareGlobalsEvalFlag) == 0) {
+ if (!DeclareGlobalsEvalFlag::decode(flags)) {
attr |= DONT_DELETE;
}
- bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0;
+ bool is_native = DeclareGlobalsNativeFlag::decode(flags);
if (is_const_property || (is_native && is_function_declaration)) {
attr |= READ_ONLY;
}
value,
attributes));
} else {
- StrictModeFlag strict_mode =
- ((flags & kDeclareGlobalsStrictModeFlag) != 0) ? kStrictMode
- : kNonStrictMode;
+ StrictModeFlag strict_mode = DeclareGlobalsStrictModeFlag::decode(flags);
RETURN_IF_EMPTY_HANDLE(isolate,
SetProperty(global,
name,
//---------------------------------------------------------------------------
// Constants used by interface to runtime functions.
-enum kDeclareGlobalsFlags {
- kDeclareGlobalsEvalFlag = 1 << 0,
- kDeclareGlobalsStrictModeFlag = 1 << 1,
- kDeclareGlobalsNativeFlag = 1 << 2
-};
+class DeclareGlobalsEvalFlag: public BitField<bool, 0, 1> {};
+class DeclareGlobalsStrictModeFlag: public BitField<StrictModeFlag, 1, 1> {};
+class DeclareGlobalsNativeFlag: public BitField<bool, 2, 1> {};
} } // namespace v8::internal
scope_contains_with_ = false;
scope_calls_eval_ = false;
// Inherit the strict mode from the parent scope.
- strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
+ strict_mode_flag_ = (outer_scope != NULL)
+ ? outer_scope->strict_mode_flag_ : kNonStrictMode;
outer_scope_calls_non_strict_eval_ = false;
inner_scope_calls_eval_ = false;
force_eager_compilation_ = false;
// Inform the scope that the corresponding code contains an eval call.
void RecordEvalCall() { if (!is_global_scope()) scope_calls_eval_ = true; }
- // Enable strict mode for the scope (unless disabled by a global flag).
- void EnableStrictMode() {
- strict_mode_ = FLAG_strict_mode;
+ // Set the strict mode flag (unless disabled by a global flag).
+ void SetStrictModeFlag(StrictModeFlag strict_mode_flag) {
+ strict_mode_flag_ = FLAG_strict_mode ? strict_mode_flag : kNonStrictMode;
}
// Position in the source where this scope begins and ends.
bool is_declaration_scope() const {
return is_eval_scope() || is_function_scope() || is_global_scope();
}
- bool is_strict_mode() const { return strict_mode_; }
+ bool is_strict_mode() const { return strict_mode_flag() == kStrictMode; }
bool is_strict_mode_eval_scope() const {
return is_eval_scope() && is_strict_mode();
}
// The type of this scope.
ScopeType type() const { return type_; }
+ // The strict mode of this scope.
+ StrictModeFlag strict_mode_flag() const { return strict_mode_flag_; }
+
// The variable corresponding the 'this' value.
Variable* receiver() { return receiver_; }
// the 'eval' call site this scope is the declaration scope.
bool scope_calls_eval_;
// This scope is a strict mode scope.
- bool strict_mode_;
+ StrictModeFlag strict_mode_flag_;
// Source positions.
int start_position_;
int end_position_;
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
+ FastNewClosureStub stub(info->strict_mode_flag());
__ Push(info);
__ CallStub(&stub);
} else {
Handle<SharedFunctionInfo> shared_info = instr->shared_info();
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && shared_info->num_literals() == 0) {
- FastNewClosureStub stub(
- shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
+ FastNewClosureStub stub(shared_info->strict_mode_flag());
__ Push(shared_info);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
bool is_done() const { return status_ == DONE; }
bool is_aborted() const { return status_ == ABORTED; }
- int strict_mode_flag() const {
- return info()->is_strict_mode() ? kStrictMode : kNonStrictMode;
+ StrictModeFlag strict_mode_flag() const {
+ return info()->strict_mode_flag();
}
LChunk* chunk() const { return chunk_; }
LOperand* object() { return inputs_[0]; }
LOperand* value() { return inputs_[1]; }
Handle<Object> name() const { return hydrogen()->name(); }
- bool strict_mode() { return hydrogen()->strict_mode(); }
+ StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ bool strict_mode() { return strict_mode_flag() == kStrictMode; }
};
--- /dev/null
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function foo() {
+ try {
+ var o = {};
+ Object.defineProperty(o, 'x', {value: 12, writable: false});
+ o.x = 13;
+ } catch(e) {
+ return true;
+ }
+ return false;
+}
+
+assertFalse(foo());
+
+function do_eval(str) {
+ "use strict";
+ return eval(str);
+}
+
+var eval_foo = do_eval('(' + foo + ')');
+for (var i = 0; i < 5; i++) assertTrue(eval_foo());
+%OptimizeFunctionOnNextCall(eval_foo);
+assertTrue(eval_foo());