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

Side by Side Diff: src/runtime.cc

Issue 379893002: Clean up and update const / var (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comment Created 6 years, 5 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/runtime.h ('k') | src/x64/full-codegen-x64.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdlib.h> 5 #include <stdlib.h>
6 #include <limits> 6 #include <limits>
7 7
8 #include "src/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/accessors.h" 10 #include "src/accessors.h"
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 Handle<Object> privates; 633 Handle<Object> privates;
634 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 634 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
635 isolate, privates, Object::GetPropertyOrElement(registry, part)); 635 isolate, privates, Object::GetPropertyOrElement(registry, part));
636 Handle<Object> symbol; 636 Handle<Object> symbol;
637 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 637 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
638 isolate, symbol, Object::GetPropertyOrElement(privates, name)); 638 isolate, symbol, Object::GetPropertyOrElement(privates, name));
639 if (!symbol->IsSymbol()) { 639 if (!symbol->IsSymbol()) {
640 ASSERT(symbol->IsUndefined()); 640 ASSERT(symbol->IsUndefined());
641 symbol = isolate->factory()->NewPrivateSymbol(); 641 symbol = isolate->factory()->NewPrivateSymbol();
642 Handle<Symbol>::cast(symbol)->set_name(*name); 642 Handle<Symbol>::cast(symbol)->set_name(*name);
643 JSObject::SetProperty(Handle<JSObject>::cast(privates), 643 JSObject::SetProperty(Handle<JSObject>::cast(privates), name, symbol, NONE,
644 name, symbol, NONE, STRICT).Assert(); 644 STRICT).Assert();
645 } 645 }
646 return *symbol; 646 return *symbol;
647 } 647 }
648 648
649 649
650 RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) { 650 RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) {
651 HandleScope scope(isolate); 651 HandleScope scope(isolate);
652 ASSERT(args.length() == 1); 652 ASSERT(args.length() == 1);
653 CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0); 653 CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
654 return *Object::ToObject(isolate, symbol).ToHandleChecked(); 654 return *Object::ToObject(isolate, symbol).ToHandleChecked();
(...skipping 1441 matching lines...) Expand 10 before | Expand all | Expand 10 after
2096 2096
2097 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) { 2097 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
2098 HandleScope scope(isolate); 2098 HandleScope scope(isolate);
2099 Handle<Object> args[1] = { name }; 2099 Handle<Object> args[1] = { name };
2100 Handle<Object> error = isolate->factory()->NewTypeError( 2100 Handle<Object> error = isolate->factory()->NewTypeError(
2101 "var_redeclaration", HandleVector(args, 1)); 2101 "var_redeclaration", HandleVector(args, 1));
2102 return isolate->Throw(*error); 2102 return isolate->Throw(*error);
2103 } 2103 }
2104 2104
2105 2105
2106 // May throw a RedeclarationError.
2107 static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global,
2108 Handle<String> name, Handle<Object> value,
2109 PropertyAttributes attr, bool is_var,
2110 bool is_const, bool is_function) {
2111 // Do the lookup own properties only, see ES5 erratum.
2112 LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN);
2113 PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it);
2114
2115 if (old_attributes != ABSENT) {
2116 // The name was declared before; check for conflicting re-declarations.
2117 if (is_const) return ThrowRedeclarationError(isolate, name);
2118
2119 // Skip var re-declarations.
2120 if (is_var) return isolate->heap()->undefined_value();
2121
2122 ASSERT(is_function);
2123 if ((old_attributes & DONT_DELETE) != 0) {
2124 // Only allow reconfiguring globals to functions in user code (no
2125 // natives, which are marked as read-only).
2126 ASSERT((attr & READ_ONLY) == 0);
2127
2128 // Check whether we can reconfigure the existing property into a
2129 // function.
2130 PropertyDetails old_details = it.property_details();
2131 // TODO(verwaest): CALLBACKS invalidly includes ExecutableAccessInfo,
2132 // which are actually data properties, not accessor properties.
2133 if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
2134 old_details.type() == CALLBACKS) {
2135 return ThrowRedeclarationError(isolate, name);
2136 }
2137 // If the existing property is not configurable, keep its attributes. Do
2138 attr = old_attributes;
2139 }
2140 }
2141
2142 // Define or redefine own property.
2143 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
2144 global, name, value, attr));
2145
2146 return isolate->heap()->undefined_value();
2147 }
2148
2149
2106 RUNTIME_FUNCTION(Runtime_DeclareGlobals) { 2150 RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
2107 HandleScope scope(isolate); 2151 HandleScope scope(isolate);
2108 ASSERT(args.length() == 3); 2152 ASSERT(args.length() == 3);
2109 Handle<GlobalObject> global(isolate->global_object()); 2153 Handle<GlobalObject> global(isolate->global_object());
2110 2154
2111 CONVERT_ARG_HANDLE_CHECKED(Context, context, 0); 2155 CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
2112 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1); 2156 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
2113 CONVERT_SMI_ARG_CHECKED(flags, 2); 2157 CONVERT_SMI_ARG_CHECKED(flags, 2);
2114 2158
2115 // Traverse the name/value pairs and set the properties. 2159 // Traverse the name/value pairs and set the properties.
2116 int length = pairs->length(); 2160 int length = pairs->length();
2117 for (int i = 0; i < length; i += 2) { 2161 for (int i = 0; i < length; i += 2) {
2118 HandleScope scope(isolate); 2162 HandleScope scope(isolate);
2119 Handle<String> name(String::cast(pairs->get(i))); 2163 Handle<String> name(String::cast(pairs->get(i)));
2120 Handle<Object> value(pairs->get(i + 1), isolate); 2164 Handle<Object> initial_value(pairs->get(i + 1), isolate);
2121 2165
2122 // We have to declare a global const property. To capture we only 2166 // We have to declare a global const property. To capture we only
2123 // assign to it when evaluating the assignment for "const x = 2167 // assign to it when evaluating the assignment for "const x =
2124 // <expr>" the initial value is the hole. 2168 // <expr>" the initial value is the hole.
2125 bool is_var = value->IsUndefined(); 2169 bool is_var = initial_value->IsUndefined();
2126 bool is_const = value->IsTheHole(); 2170 bool is_const = initial_value->IsTheHole();
2127 bool is_function = value->IsSharedFunctionInfo(); 2171 bool is_function = initial_value->IsSharedFunctionInfo();
2128 ASSERT(is_var + is_const + is_function == 1); 2172 ASSERT(is_var + is_const + is_function == 1);
2129 2173
2130 if (is_var || is_const) { 2174 Handle<Object> value;
2131 // Lookup the property in the global object, and don't set the 2175 if (is_function) {
2132 // value of the variable if the property is already there.
2133 // Do the lookup own properties only, see ES5 erratum.
2134 LookupResult lookup(isolate);
2135 global->LookupOwn(name, &lookup, true);
2136 if (lookup.IsFound()) {
2137 // We found an existing property. Unless it was an interceptor
2138 // that claims the property is absent, skip this declaration.
2139 if (!lookup.IsInterceptor()) continue;
2140 if (JSReceiver::GetPropertyAttributes(global, name) != ABSENT) continue;
2141 // Fall-through and introduce the absent property by using
2142 // SetProperty.
2143 }
2144 } else if (is_function) {
2145 // Copy the function and update its context. Use it as value. 2176 // Copy the function and update its context. Use it as value.
2146 Handle<SharedFunctionInfo> shared = 2177 Handle<SharedFunctionInfo> shared =
2147 Handle<SharedFunctionInfo>::cast(value); 2178 Handle<SharedFunctionInfo>::cast(initial_value);
2148 Handle<JSFunction> function = 2179 Handle<JSFunction> function =
2149 isolate->factory()->NewFunctionFromSharedFunctionInfo( 2180 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
2150 shared, context, TENURED); 2181 TENURED);
2151 value = function; 2182 value = function;
2183 } else {
2184 value = isolate->factory()->undefined_value();
2152 } 2185 }
2153 2186
2154 LookupResult lookup(isolate);
2155 global->LookupOwn(name, &lookup, true);
2156
2157 // Compute the property attributes. According to ECMA-262, 2187 // Compute the property attributes. According to ECMA-262,
2158 // the property must be non-configurable except in eval. 2188 // the property must be non-configurable except in eval.
2189 bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2190 bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2159 int attr = NONE; 2191 int attr = NONE;
2160 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); 2192 if (is_const) attr |= READ_ONLY;
2161 if (!is_eval) { 2193 if (is_function && is_native) attr |= READ_ONLY;
2162 attr |= DONT_DELETE; 2194 if (!is_const && !is_eval) attr |= DONT_DELETE;
2163 }
2164 bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2165 if (is_const || (is_native && is_function)) {
2166 attr |= READ_ONLY;
2167 }
2168 2195
2169 StrictMode strict_mode = DeclareGlobalsStrictMode::decode(flags); 2196 Object* result = DeclareGlobals(isolate, global, name, value,
2170 2197 static_cast<PropertyAttributes>(attr),
2171 if (!lookup.IsFound() || is_function) { 2198 is_var, is_const, is_function);
2172 // If the own property exists, check that we can reconfigure it 2199 if (isolate->has_pending_exception()) return result;
2173 // as required for function declarations.
2174 if (lookup.IsFound() && lookup.IsDontDelete()) {
2175 if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
2176 lookup.IsPropertyCallbacks()) {
2177 return ThrowRedeclarationError(isolate, name);
2178 }
2179 // If the existing property is not configurable, keep its attributes.
2180 attr = lookup.GetAttributes();
2181 }
2182 // Define or redefine own property.
2183 RETURN_FAILURE_ON_EXCEPTION(isolate,
2184 JSObject::SetOwnPropertyIgnoreAttributes(
2185 global, name, value, static_cast<PropertyAttributes>(attr)));
2186 } else {
2187 // Do a [[Put]] on the existing (own) property.
2188 RETURN_FAILURE_ON_EXCEPTION(
2189 isolate,
2190 JSObject::SetProperty(
2191 global, name, value, static_cast<PropertyAttributes>(attr),
2192 strict_mode));
2193 }
2194 }
2195
2196 ASSERT(!isolate->has_pending_exception());
2197 return isolate->heap()->undefined_value();
2198 }
2199
2200
2201 RUNTIME_FUNCTION(Runtime_DeclareContextSlot) {
2202 HandleScope scope(isolate);
2203 ASSERT(args.length() == 4);
2204
2205 // Declarations are always made in a function or native context. In the
2206 // case of eval code, the context passed is the context of the caller,
2207 // which may be some nested context and not the declaration context.
2208 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0);
2209 Handle<Context> context(context_arg->declaration_context());
2210 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
2211 CONVERT_SMI_ARG_CHECKED(mode_arg, 2);
2212 PropertyAttributes mode = static_cast<PropertyAttributes>(mode_arg);
2213 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
2214 CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
2215
2216 int index;
2217 PropertyAttributes attributes;
2218 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2219 BindingFlags binding_flags;
2220 Handle<Object> holder =
2221 context->Lookup(name, flags, &index, &attributes, &binding_flags);
2222
2223 if (attributes != ABSENT) {
2224 // The name was declared before; check for conflicting re-declarations.
2225 // Note: this is actually inconsistent with what happens for globals (where
2226 // we silently ignore such declarations).
2227 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
2228 // Functions are not read-only.
2229 ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
2230 return ThrowRedeclarationError(isolate, name);
2231 }
2232
2233 // Initialize it if necessary.
2234 if (*initial_value != NULL) {
2235 if (index >= 0) {
2236 ASSERT(holder.is_identical_to(context));
2237 if (((attributes & READ_ONLY) == 0) ||
2238 context->get(index)->IsTheHole()) {
2239 context->set(index, *initial_value);
2240 }
2241 } else {
2242 // Slow case: The property is in the context extension object of a
2243 // function context or the global object of a native context.
2244 Handle<JSObject> object = Handle<JSObject>::cast(holder);
2245 RETURN_FAILURE_ON_EXCEPTION(
2246 isolate,
2247 JSReceiver::SetProperty(object, name, initial_value, mode, SLOPPY));
2248 }
2249 }
2250
2251 } else {
2252 // The property is not in the function context. It needs to be
2253 // "declared" in the function context's extension context or as a
2254 // property of the the global object.
2255 Handle<JSObject> object;
2256 if (context->has_extension()) {
2257 object = Handle<JSObject>(JSObject::cast(context->extension()));
2258 } else {
2259 // Context extension objects are allocated lazily.
2260 ASSERT(context->IsFunctionContext());
2261 object = isolate->factory()->NewJSObject(
2262 isolate->context_extension_function());
2263 context->set_extension(*object);
2264 }
2265 ASSERT(*object != NULL);
2266
2267 // Declare the property by setting it to the initial value if provided,
2268 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
2269 // constant declarations).
2270 ASSERT(!JSReceiver::HasOwnProperty(object, name));
2271 Handle<Object> value(isolate->heap()->undefined_value(), isolate);
2272 if (*initial_value != NULL) value = initial_value;
2273 // Declaring a const context slot is a conflicting declaration if
2274 // there is a callback with that name in a prototype. It is
2275 // allowed to introduce const variables in
2276 // JSContextExtensionObjects. They are treated specially in
2277 // SetProperty and no setters are invoked for those since they are
2278 // not real JSObjects.
2279 if (initial_value->IsTheHole() &&
2280 !object->IsJSContextExtensionObject()) {
2281 LookupResult lookup(isolate);
2282 object->Lookup(name, &lookup);
2283 if (lookup.IsPropertyCallbacks()) {
2284 return ThrowRedeclarationError(isolate, name);
2285 }
2286 }
2287 if (object->IsJSGlobalObject()) {
2288 // Define own property on the global object.
2289 RETURN_FAILURE_ON_EXCEPTION(isolate,
2290 JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, mode));
2291 } else {
2292 RETURN_FAILURE_ON_EXCEPTION(isolate,
2293 JSReceiver::SetProperty(object, name, value, mode, SLOPPY));
2294 }
2295 } 2200 }
2296 2201
2297 return isolate->heap()->undefined_value(); 2202 return isolate->heap()->undefined_value();
2298 } 2203 }
2299 2204
2300 2205
2301 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { 2206 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
2302 HandleScope scope(isolate); 2207 HandleScope scope(isolate);
2303 // args[0] == name 2208 // args[0] == name
2304 // args[1] == language_mode 2209 // args[1] == language_mode
2305 // args[2] == value (optional) 2210 // args[2] == value (optional)
2306 2211
2307 // Determine if we need to assign to the variable if it already 2212 // Determine if we need to assign to the variable if it already
2308 // exists (based on the number of arguments). 2213 // exists (based on the number of arguments).
2309 RUNTIME_ASSERT(args.length() == 2 || args.length() == 3); 2214 RUNTIME_ASSERT(args.length() == 3);
2310 bool assign = args.length() == 3;
2311 2215
2312 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 2216 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2313 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1); 2217 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
2218 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2314 2219
2315 // According to ECMA-262, section 12.2, page 62, the property must 2220 Handle<GlobalObject> global(isolate->context()->global_object());
2316 // not be deletable. 2221 Handle<Object> result;
2317 PropertyAttributes attributes = DONT_DELETE; 2222 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2318 2223 isolate, result,
2319 // Lookup the property as own on the global object. If it isn't 2224 JSReceiver::SetProperty(global, name, value, NONE, strict_mode));
2320 // there, there is a property with this name in the prototype chain. 2225 return *result;
2321 // We follow Safari and Firefox behavior and only set the property
2322 // if there is an explicit initialization value that we have
2323 // to assign to the property.
2324 // Note that objects can have hidden prototypes, so we need to traverse
2325 // the whole chain of hidden prototypes to do an 'own' lookup.
2326 LookupResult lookup(isolate);
2327 isolate->context()->global_object()->LookupOwn(name, &lookup, true);
2328 if (lookup.IsInterceptor()) {
2329 Handle<JSObject> holder(lookup.holder());
2330 PropertyAttributes intercepted =
2331 JSReceiver::GetPropertyAttributes(holder, name);
2332 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
2333 // Found an interceptor that's not read only.
2334 if (assign) {
2335 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2336 Handle<Object> result;
2337 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2338 isolate, result,
2339 JSObject::SetPropertyForResult(
2340 holder, &lookup, name, value, attributes, strict_mode));
2341 return *result;
2342 } else {
2343 return isolate->heap()->undefined_value();
2344 }
2345 }
2346 }
2347
2348 if (assign) {
2349 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2350 Handle<GlobalObject> global(isolate->context()->global_object());
2351 Handle<Object> result;
2352 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2353 isolate, result,
2354 JSReceiver::SetProperty(global, name, value, attributes, strict_mode));
2355 return *result;
2356 }
2357 return isolate->heap()->undefined_value();
2358 } 2226 }
2359 2227
2360 2228
2361 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) { 2229 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
2362 SealHandleScope shs(isolate); 2230 HandleScope handle_scope(isolate);
2363 // All constants are declared with an initial value. The name 2231 // All constants are declared with an initial value. The name
2364 // of the constant is the first argument and the initial value 2232 // of the constant is the first argument and the initial value
2365 // is the second. 2233 // is the second.
2366 RUNTIME_ASSERT(args.length() == 2); 2234 RUNTIME_ASSERT(args.length() == 2);
2367 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 2235 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2368 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); 2236 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
2369 2237
2370 // Get the current global object from top. 2238 Handle<GlobalObject> global = isolate->global_object();
2371 GlobalObject* global = isolate->context()->global_object();
2372 2239
2373 // According to ECMA-262, section 12.2, page 62, the property must 2240 // Lookup the property as own on the global object.
2374 // not be deletable. Since it's a const, it must be READ_ONLY too. 2241 LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN);
2375 PropertyAttributes attributes = 2242 PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it);
2243
2244 PropertyAttributes attr =
2376 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); 2245 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2377 2246 // Set the value if the property is either missing, or the property attributes
2378 // Lookup the property as own on the global object. If it isn't 2247 // allow setting the value without invoking an accessor.
2379 // there, we add the property and take special precautions to always 2248 if (it.IsFound()) {
2380 // add it even in case of callbacks in the prototype chain (this rules 2249 // Ignore if we can't reconfigure the value.
2381 // out using SetProperty). We use SetOwnPropertyIgnoreAttributes instead 2250 if ((old_attributes & DONT_DELETE) != 0) {
2382 LookupResult lookup(isolate); 2251 if ((old_attributes & READ_ONLY) != 0 ||
2383 global->LookupOwn(name, &lookup); 2252 it.property_kind() == LookupIterator::ACCESSOR) {
2384 if (!lookup.IsFound()) { 2253 return *value;
2385 HandleScope handle_scope(isolate); 2254 }
2386 Handle<GlobalObject> global(isolate->context()->global_object()); 2255 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
2387 JSObject::AddProperty(global, name, value, attributes); 2256 }
2388 return *value;
2389 } 2257 }
2390 2258
2391 if (!lookup.IsReadOnly()) { 2259 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
2392 // Restore global object from context (in case of GC) and continue 2260 global, name, value, attr));
2393 // with setting the value.
2394 HandleScope handle_scope(isolate);
2395 Handle<GlobalObject> global(isolate->context()->global_object());
2396 2261
2397 // BUG 1213575: Handle the case where we have to set a read-only
2398 // property through an interceptor and only do it if it's
2399 // uninitialized, e.g. the hole. Nirk...
2400 // Passing sloppy mode because the property is writable.
2401 RETURN_FAILURE_ON_EXCEPTION(
2402 isolate,
2403 JSReceiver::SetProperty(global, name, value, attributes, SLOPPY));
2404 return *value;
2405 }
2406
2407 // Set the value, but only if we're assigning the initial value to a
2408 // constant. For now, we determine this by checking if the
2409 // current value is the hole.
2410 // Strict mode handling not needed (const is disallowed in strict mode).
2411 if (lookup.IsField()) {
2412 FixedArray* properties = global->properties();
2413 int index = lookup.GetFieldIndex().outobject_array_index();
2414 if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
2415 properties->set(index, *value);
2416 }
2417 } else if (lookup.IsNormal()) {
2418 if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
2419 !lookup.IsReadOnly()) {
2420 HandleScope scope(isolate);
2421 JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
2422 }
2423 } else {
2424 // Ignore re-initialization of constants that have already been
2425 // assigned a constant value.
2426 ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
2427 }
2428
2429 // Use the set value as the result of the operation.
2430 return *value; 2262 return *value;
2431 } 2263 }
2432 2264
2433 2265
2434 RUNTIME_FUNCTION(Runtime_InitializeConstContextSlot) { 2266 RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
2267 HandleScope scope(isolate);
2268 ASSERT(args.length() == 4);
2269
2270 // Declarations are always made in a function, native, or global context. In
2271 // the case of eval code, the context passed is the context of the caller,
2272 // which may be some nested context and not the declaration context.
2273 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0);
2274 Handle<Context> context(context_arg->declaration_context());
2275 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
2276 CONVERT_SMI_ARG_CHECKED(attr_arg, 2);
2277 PropertyAttributes attr = static_cast<PropertyAttributes>(attr_arg);
2278 RUNTIME_ASSERT(attr == READ_ONLY || attr == NONE);
2279 CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
2280
2281 // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
2282 bool is_var = *initial_value == NULL;
2283 bool is_const = initial_value->IsTheHole();
2284 bool is_function = initial_value->IsJSFunction();
2285 ASSERT(is_var + is_const + is_function == 1);
2286
2287 int index;
2288 PropertyAttributes attributes;
2289 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2290 BindingFlags binding_flags;
2291 Handle<Object> holder =
2292 context->Lookup(name, flags, &index, &attributes, &binding_flags);
2293
2294 Handle<JSObject> object;
2295 Handle<Object> value =
2296 is_function ? initial_value
2297 : Handle<Object>::cast(isolate->factory()->undefined_value());
2298
2299 // TODO(verwaest): This case should probably not be covered by this function,
2300 // but by DeclareGlobals instead.
2301 if ((attributes != ABSENT && holder->IsJSGlobalObject()) ||
2302 (context_arg->has_extension() &&
2303 context_arg->extension()->IsJSGlobalObject())) {
2304 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
2305 value, attr, is_var, is_const, is_function);
2306 }
2307
2308 if (attributes != ABSENT) {
2309 // The name was declared before; check for conflicting re-declarations.
2310 if (is_const || (attributes & READ_ONLY) != 0) {
2311 return ThrowRedeclarationError(isolate, name);
2312 }
2313
2314 // Skip var re-declarations.
2315 if (is_var) return isolate->heap()->undefined_value();
2316
2317 ASSERT(is_function);
2318 if (index >= 0) {
2319 ASSERT(holder.is_identical_to(context));
2320 context->set(index, *initial_value);
2321 return isolate->heap()->undefined_value();
2322 }
2323
2324 object = Handle<JSObject>::cast(holder);
2325
2326 } else if (context->has_extension()) {
2327 object = handle(JSObject::cast(context->extension()));
2328 ASSERT(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
2329 } else {
2330 ASSERT(context->IsFunctionContext());
2331 object =
2332 isolate->factory()->NewJSObject(isolate->context_extension_function());
2333 context->set_extension(*object);
2334 }
2335
2336 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
2337 object, name, value, attr));
2338
2339 return isolate->heap()->undefined_value();
2340 }
2341
2342
2343 RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
2435 HandleScope scope(isolate); 2344 HandleScope scope(isolate);
2436 ASSERT(args.length() == 3); 2345 ASSERT(args.length() == 3);
2437 2346
2438 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 2347 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
2439 ASSERT(!value->IsTheHole()); 2348 ASSERT(!value->IsTheHole());
2440 // Initializations are always done in a function or native context. 2349 // Initializations are always done in a function or native context.
2441 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1); 2350 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
2442 Handle<Context> context(context_arg->declaration_context()); 2351 Handle<Context> context(context_arg->declaration_context());
2443 CONVERT_ARG_HANDLE_CHECKED(String, name, 2); 2352 CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
2444 2353
2445 int index; 2354 int index;
2446 PropertyAttributes attributes; 2355 PropertyAttributes attributes;
2447 ContextLookupFlags flags = FOLLOW_CHAINS; 2356 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2448 BindingFlags binding_flags; 2357 BindingFlags binding_flags;
2449 Handle<Object> holder = 2358 Handle<Object> holder =
2450 context->Lookup(name, flags, &index, &attributes, &binding_flags); 2359 context->Lookup(name, flags, &index, &attributes, &binding_flags);
2451 2360
2452 if (index >= 0) { 2361 if (index >= 0) {
2453 ASSERT(holder->IsContext()); 2362 ASSERT(holder->IsContext());
2454 // Property was found in a context. Perform the assignment if we 2363 // Property was found in a context. Perform the assignment if the constant
2455 // found some non-constant or an uninitialized constant. 2364 // was uninitialized.
2456 Handle<Context> context = Handle<Context>::cast(holder); 2365 Handle<Context> context = Handle<Context>::cast(holder);
2457 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { 2366 ASSERT((attributes & READ_ONLY) != 0);
2458 context->set(index, *value); 2367 if (context->get(index)->IsTheHole()) context->set(index, *value);
2459 }
2460 return *value; 2368 return *value;
2461 } 2369 }
2462 2370
2463 // The property could not be found, we introduce it as a property of the 2371 PropertyAttributes attr =
2464 // global object. 2372 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2373
2374 // Strict mode handling not needed (legacy const is disallowed in strict
2375 // mode).
2376
2377 // The declared const was configurable, and may have been deleted in the
2378 // meanwhile. If so, re-introduce the variable in the context extension.
2379 ASSERT(context_arg->has_extension());
2465 if (attributes == ABSENT) { 2380 if (attributes == ABSENT) {
2466 Handle<JSObject> global = Handle<JSObject>( 2381 holder = handle(context_arg->extension(), isolate);
2467 isolate->context()->global_object()); 2382 } else {
2468 // Strict mode not needed (const disallowed in strict mode). 2383 // For JSContextExtensionObjects, the initializer can be run multiple times
2469 RETURN_FAILURE_ON_EXCEPTION( 2384 // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the
2470 isolate, 2385 // first assignment should go through. For JSGlobalObjects, additionally any
2471 JSReceiver::SetProperty(global, name, value, NONE, SLOPPY)); 2386 // code can run in between that modifies the declared property.
2472 return *value; 2387 ASSERT(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
2388
2389 LookupIterator it(holder, name, LookupIterator::CHECK_HIDDEN);
2390 PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it);
2391
2392 // Ignore if we can't reconfigure the value.
2393 if ((old_attributes & DONT_DELETE) != 0) {
2394 if ((old_attributes & READ_ONLY) != 0 ||
2395 it.property_kind() == LookupIterator::ACCESSOR) {
2396 return *value;
2397 }
2398 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
2399 }
2473 } 2400 }
2474 2401
2475 // The property was present in some function's context extension object, 2402 RETURN_FAILURE_ON_EXCEPTION(
2476 // as a property on the subject of a with, or as a property of the global 2403 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
2477 // object. 2404 Handle<JSObject>::cast(holder), name, value, attr));
2478 //
2479 // In most situations, eval-introduced consts should still be present in
2480 // the context extension object. However, because declaration and
2481 // initialization are separate, the property might have been deleted
2482 // before we reach the initialization point.
2483 //
2484 // Example:
2485 //
2486 // function f() { eval("delete x; const x;"); }
2487 //
2488 // In that case, the initialization behaves like a normal assignment.
2489 Handle<JSObject> object = Handle<JSObject>::cast(holder);
2490
2491 if (*object == context->extension()) {
2492 // This is the property that was introduced by the const declaration.
2493 // Set it if it hasn't been set before. NOTE: We cannot use
2494 // GetProperty() to get the current value as it 'unholes' the value.
2495 LookupResult lookup(isolate);
2496 object->LookupOwnRealNamedProperty(name, &lookup);
2497 ASSERT(lookup.IsFound()); // the property was declared
2498 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
2499
2500 if (lookup.IsField()) {
2501 FixedArray* properties = object->properties();
2502 FieldIndex index = lookup.GetFieldIndex();
2503 ASSERT(!index.is_inobject());
2504 if (properties->get(index.outobject_array_index())->IsTheHole()) {
2505 properties->set(index.outobject_array_index(), *value);
2506 }
2507 } else if (lookup.IsNormal()) {
2508 if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
2509 JSObject::SetNormalizedProperty(object, &lookup, value);
2510 }
2511 } else {
2512 // We should not reach here. Any real, named property should be
2513 // either a field or a dictionary slot.
2514 UNREACHABLE();
2515 }
2516 } else {
2517 // The property was found on some other object. Set it if it is not a
2518 // read-only property.
2519 if ((attributes & READ_ONLY) == 0) {
2520 // Strict mode not needed (const disallowed in strict mode).
2521 RETURN_FAILURE_ON_EXCEPTION(
2522 isolate,
2523 JSReceiver::SetProperty(object, name, value, attributes, SLOPPY));
2524 }
2525 }
2526 2405
2527 return *value; 2406 return *value;
2528 } 2407 }
2529 2408
2530 2409
2531 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) { 2410 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
2532 HandleScope scope(isolate); 2411 HandleScope scope(isolate);
2533 ASSERT(args.length() == 2); 2412 ASSERT(args.length() == 2);
2534 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 2413 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2535 CONVERT_SMI_ARG_CHECKED(properties, 1); 2414 CONVERT_SMI_ARG_CHECKED(properties, 1);
(...skipping 6779 matching lines...) Expand 10 before | Expand all | Expand 10 after
9315 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadContextSlot) { 9194 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadContextSlot) {
9316 return LoadContextSlotHelper(args, isolate, true); 9195 return LoadContextSlotHelper(args, isolate, true);
9317 } 9196 }
9318 9197
9319 9198
9320 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadContextSlotNoReferenceError) { 9199 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadContextSlotNoReferenceError) {
9321 return LoadContextSlotHelper(args, isolate, false); 9200 return LoadContextSlotHelper(args, isolate, false);
9322 } 9201 }
9323 9202
9324 9203
9325 RUNTIME_FUNCTION(Runtime_StoreContextSlot) { 9204 RUNTIME_FUNCTION(Runtime_StoreLookupSlot) {
9326 HandleScope scope(isolate); 9205 HandleScope scope(isolate);
9327 ASSERT(args.length() == 4); 9206 ASSERT(args.length() == 4);
9328 9207
9329 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 9208 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
9330 CONVERT_ARG_HANDLE_CHECKED(Context, context, 1); 9209 CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9331 CONVERT_ARG_HANDLE_CHECKED(String, name, 2); 9210 CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
9332 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3); 9211 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
9333 9212
9334 int index; 9213 int index;
9335 PropertyAttributes attributes; 9214 PropertyAttributes attributes;
9336 ContextLookupFlags flags = FOLLOW_CHAINS; 9215 ContextLookupFlags flags = FOLLOW_CHAINS;
9337 BindingFlags binding_flags; 9216 BindingFlags binding_flags;
9338 Handle<Object> holder = context->Lookup(name, 9217 Handle<Object> holder = context->Lookup(name,
9339 flags, 9218 flags,
9340 &index, 9219 &index,
9341 &attributes, 9220 &attributes,
9342 &binding_flags); 9221 &binding_flags);
9222 // In case of JSProxy, an exception might have been thrown.
9343 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 9223 if (isolate->has_pending_exception()) return isolate->heap()->exception();
9344 9224
9225 // The property was found in a context slot.
9345 if (index >= 0) { 9226 if (index >= 0) {
9346 // The property was found in a context slot.
9347 Handle<Context> context = Handle<Context>::cast(holder);
9348 if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9349 context->get(index)->IsTheHole()) {
9350 Handle<Object> error =
9351 isolate->factory()->NewReferenceError("not_defined",
9352 HandleVector(&name, 1));
9353 return isolate->Throw(*error);
9354 }
9355 // Ignore if read_only variable.
9356 if ((attributes & READ_ONLY) == 0) { 9227 if ((attributes & READ_ONLY) == 0) {
9357 // Context is a fixed array and set cannot fail. 9228 Handle<Context>::cast(holder)->set(index, *value);
9358 context->set(index, *value);
9359 } else if (strict_mode == STRICT) { 9229 } else if (strict_mode == STRICT) {
9360 // Setting read only property in strict mode. 9230 // Setting read only property in strict mode.
9361 Handle<Object> error = 9231 Handle<Object> error =
9362 isolate->factory()->NewTypeError("strict_cannot_assign", 9232 isolate->factory()->NewTypeError("strict_cannot_assign",
9363 HandleVector(&name, 1)); 9233 HandleVector(&name, 1));
9364 return isolate->Throw(*error); 9234 return isolate->Throw(*error);
9365 } 9235 }
9366 return *value; 9236 return *value;
9367 } 9237 }
9368 9238
9369 // Slow case: The property is not in a context slot. It is either in a 9239 // Slow case: The property is not in a context slot. It is either in a
9370 // context extension object, a property of the subject of a with, or a 9240 // context extension object, a property of the subject of a with, or a
9371 // property of the global object. 9241 // property of the global object.
9372 Handle<JSReceiver> object; 9242 Handle<JSReceiver> object;
9373 9243 if (attributes != ABSENT) {
9374 if (!holder.is_null()) {
9375 // The property exists on the holder. 9244 // The property exists on the holder.
9376 object = Handle<JSReceiver>::cast(holder); 9245 object = Handle<JSReceiver>::cast(holder);
9246 } else if (strict_mode == STRICT) {
9247 // If absent in strict mode: throw.
9248 Handle<Object> error = isolate->factory()->NewReferenceError(
9249 "not_defined", HandleVector(&name, 1));
9250 return isolate->Throw(*error);
9377 } else { 9251 } else {
9378 // The property was not found. 9252 // If absent in sloppy mode: add the property to the global object.
9379 ASSERT(attributes == ABSENT); 9253 object = Handle<JSReceiver>(context->global_object());
9380
9381 if (strict_mode == STRICT) {
9382 // Throw in strict mode (assignment to undefined variable).
9383 Handle<Object> error =
9384 isolate->factory()->NewReferenceError(
9385 "not_defined", HandleVector(&name, 1));
9386 return isolate->Throw(*error);
9387 }
9388 // In sloppy mode, the property is added to the global object.
9389 attributes = NONE;
9390 object = Handle<JSReceiver>(isolate->context()->global_object());
9391 } 9254 }
9392 9255
9393 // Set the property if it's not read only or doesn't yet exist. 9256 RETURN_FAILURE_ON_EXCEPTION(
9394 if ((attributes & READ_ONLY) == 0 || 9257 isolate, JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9395 (JSReceiver::GetOwnPropertyAttributes(object, name) == ABSENT)) { 9258
9396 RETURN_FAILURE_ON_EXCEPTION(
9397 isolate,
9398 JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9399 } else if (strict_mode == STRICT && (attributes & READ_ONLY) != 0) {
9400 // Setting read only property in strict mode.
9401 Handle<Object> error =
9402 isolate->factory()->NewTypeError(
9403 "strict_cannot_assign", HandleVector(&name, 1));
9404 return isolate->Throw(*error);
9405 }
9406 return *value; 9259 return *value;
9407 } 9260 }
9408 9261
9409 9262
9410 RUNTIME_FUNCTION(Runtime_Throw) { 9263 RUNTIME_FUNCTION(Runtime_Throw) {
9411 HandleScope scope(isolate); 9264 HandleScope scope(isolate);
9412 ASSERT(args.length() == 1); 9265 ASSERT(args.length() == 1);
9413 9266
9414 return isolate->Throw(args[0]); 9267 return isolate->Throw(args[0]);
9415 } 9268 }
(...skipping 5689 matching lines...) Expand 10 before | Expand all | Expand 10 after
15105 } 14958 }
15106 return NULL; 14959 return NULL;
15107 } 14960 }
15108 14961
15109 14962
15110 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { 14963 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
15111 return &(kIntrinsicFunctions[static_cast<int>(id)]); 14964 return &(kIntrinsicFunctions[static_cast<int>(id)]);
15112 } 14965 }
15113 14966
15114 } } // namespace v8::internal 14967 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698