Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1 | // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 5 | #include "src/runtime/runtime-utils.h" |
| 6 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 7 | #include <stdlib.h> |
| 8 | #include <limits> |
| 9 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 10 | #include "src/arguments.h" |
| 11 | #include "src/debug/debug.h" |
| 12 | #include "src/frames-inl.h" |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 13 | #include "src/isolate-inl.h" |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 14 | #include "src/messages.h" |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 15 | #include "src/runtime/runtime.h" |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 16 | |
| 17 | namespace v8 { |
| 18 | namespace internal { |
| 19 | |
| 20 | |
| 21 | RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) { |
| 22 | HandleScope scope(isolate); |
| 23 | DCHECK(args.length() == 0); |
| 24 | THROW_NEW_ERROR_RETURN_FAILURE( |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 25 | isolate, NewReferenceError(MessageTemplate::kNonMethod)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 26 | } |
| 27 | |
| 28 | |
| 29 | RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) { |
| 30 | HandleScope scope(isolate); |
| 31 | DCHECK(args.length() == 0); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 32 | THROW_NEW_ERROR_RETURN_FAILURE( |
| 33 | isolate, NewReferenceError(MessageTemplate::kUnsupportedSuper)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 37 | RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 38 | HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 39 | DCHECK(args.length() == 1); |
| 40 | CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0); |
| 41 | Handle<Object> name(constructor->shared()->name(), isolate); |
| 42 | THROW_NEW_ERROR_RETURN_FAILURE( |
| 43 | isolate, NewTypeError(MessageTemplate::kConstructorNonCallable, name)); |
| 44 | } |
| 45 | |
| 46 | |
| 47 | RUNTIME_FUNCTION(Runtime_ThrowArrayNotSubclassableError) { |
| 48 | HandleScope scope(isolate); |
| 49 | DCHECK(args.length() == 0); |
| 50 | THROW_NEW_ERROR_RETURN_FAILURE( |
| 51 | isolate, NewTypeError(MessageTemplate::kArrayNotSubclassable)); |
| 52 | } |
| 53 | |
| 54 | |
| 55 | static Object* ThrowStaticPrototypeError(Isolate* isolate) { |
| 56 | THROW_NEW_ERROR_RETURN_FAILURE( |
| 57 | isolate, NewTypeError(MessageTemplate::kStaticPrototype)); |
| 58 | } |
| 59 | |
| 60 | |
| 61 | RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) { |
| 62 | HandleScope scope(isolate); |
| 63 | DCHECK(args.length() == 0); |
| 64 | return ThrowStaticPrototypeError(isolate); |
| 65 | } |
| 66 | |
| 67 | |
| 68 | RUNTIME_FUNCTION(Runtime_ThrowIfStaticPrototype) { |
| 69 | HandleScope scope(isolate); |
| 70 | DCHECK(args.length() == 1); |
| 71 | CONVERT_ARG_HANDLE_CHECKED(Name, name, 0); |
| 72 | if (Name::Equals(name, isolate->factory()->prototype_string())) { |
| 73 | return ThrowStaticPrototypeError(isolate); |
| 74 | } |
| 75 | return *name; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | |
| 79 | RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) { |
| 80 | DCHECK(args.length() == 0); |
| 81 | return isolate->heap()->home_object_symbol(); |
| 82 | } |
| 83 | |
| 84 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 85 | static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name, |
| 86 | Handle<Object> super_class, |
| 87 | Handle<JSFunction> constructor, |
| 88 | int start_position, int end_position) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 89 | Handle<Object> prototype_parent; |
| 90 | Handle<Object> constructor_parent; |
| 91 | |
| 92 | if (super_class->IsTheHole()) { |
| 93 | prototype_parent = isolate->initial_object_prototype(); |
| 94 | } else { |
| 95 | if (super_class->IsNull()) { |
| 96 | prototype_parent = isolate->factory()->null_value(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 97 | } else if (super_class->IsConstructor()) { |
| 98 | if (super_class->IsJSFunction() && |
| 99 | Handle<JSFunction>::cast(super_class)->shared()->is_generator()) { |
| 100 | THROW_NEW_ERROR( |
| 101 | isolate, |
| 102 | NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class), |
| 103 | Object); |
| 104 | } |
| 105 | ASSIGN_RETURN_ON_EXCEPTION( |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 106 | isolate, prototype_parent, |
| 107 | Runtime::GetObjectProperty(isolate, super_class, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 108 | isolate->factory()->prototype_string(), |
| 109 | SLOPPY), |
| 110 | Object); |
| 111 | if (!prototype_parent->IsNull() && !prototype_parent->IsJSReceiver()) { |
| 112 | THROW_NEW_ERROR( |
| 113 | isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject, |
| 114 | prototype_parent), |
| 115 | Object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 116 | } |
| 117 | constructor_parent = super_class; |
| 118 | } else { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 119 | THROW_NEW_ERROR( |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 120 | isolate, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 121 | NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class), |
| 122 | Object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 123 | } |
| 124 | } |
| 125 | |
| 126 | Handle<Map> map = |
| 127 | isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 128 | map->set_is_prototype_map(true); |
| 129 | if (constructor->map()->is_strong()) { |
| 130 | map->set_is_strong(); |
| 131 | if (super_class->IsNull()) { |
| 132 | // Strong class is not permitted to extend null. |
| 133 | THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kStrongExtendNull), |
| 134 | Object); |
| 135 | } |
| 136 | } |
| 137 | Map::SetPrototype(map, prototype_parent); |
| 138 | map->SetConstructor(*constructor); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 139 | Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map); |
| 140 | |
| 141 | Handle<String> name_string = name->IsString() |
| 142 | ? Handle<String>::cast(name) |
| 143 | : isolate->factory()->empty_string(); |
| 144 | constructor->shared()->set_name(*name_string); |
| 145 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 146 | if (!super_class->IsTheHole()) { |
| 147 | // Derived classes, just like builtins, don't create implicit receivers in |
| 148 | // [[construct]]. Instead they just set up new.target and call into the |
| 149 | // constructor. Hence we can reuse the builtins construct stub for derived |
| 150 | // classes. |
| 151 | Handle<Code> stub(isolate->builtins()->JSBuiltinsConstructStub()); |
| 152 | constructor->shared()->set_construct_stub(*stub); |
| 153 | } |
| 154 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 155 | JSFunction::SetPrototype(constructor, prototype); |
| 156 | PropertyAttributes attribs = |
| 157 | static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 158 | RETURN_ON_EXCEPTION(isolate, |
| 159 | JSObject::SetOwnPropertyIgnoreAttributes( |
| 160 | constructor, isolate->factory()->prototype_string(), |
| 161 | prototype, attribs), |
| 162 | Object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 163 | |
| 164 | // TODO(arv): Only do this conditionally. |
| 165 | Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 166 | RETURN_ON_EXCEPTION( |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 167 | isolate, JSObject::SetOwnPropertyIgnoreAttributes( |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 168 | constructor, home_object_symbol, prototype, DONT_ENUM), |
| 169 | Object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 170 | |
| 171 | if (!constructor_parent.is_null()) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 172 | MAYBE_RETURN_NULL(JSObject::SetPrototype(constructor, constructor_parent, |
| 173 | false, Object::THROW_ON_ERROR)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 174 | } |
| 175 | |
| 176 | JSObject::AddProperty(prototype, isolate->factory()->constructor_string(), |
| 177 | constructor, DONT_ENUM); |
| 178 | |
| 179 | // Install private properties that are used to construct the FunctionToString. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 180 | RETURN_ON_EXCEPTION( |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 181 | isolate, |
| 182 | Object::SetProperty( |
| 183 | constructor, isolate->factory()->class_start_position_symbol(), |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 184 | handle(Smi::FromInt(start_position), isolate), STRICT), |
| 185 | Object); |
| 186 | RETURN_ON_EXCEPTION( |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 187 | isolate, Object::SetProperty( |
| 188 | constructor, isolate->factory()->class_end_position_symbol(), |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 189 | handle(Smi::FromInt(end_position), isolate), STRICT), |
| 190 | Object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 191 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 192 | return constructor; |
| 193 | } |
| 194 | |
| 195 | |
| 196 | RUNTIME_FUNCTION(Runtime_DefineClass) { |
| 197 | HandleScope scope(isolate); |
| 198 | DCHECK(args.length() == 5); |
| 199 | CONVERT_ARG_HANDLE_CHECKED(Object, name, 0); |
| 200 | CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1); |
| 201 | CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2); |
| 202 | CONVERT_SMI_ARG_CHECKED(start_position, 3); |
| 203 | CONVERT_SMI_ARG_CHECKED(end_position, 4); |
| 204 | |
| 205 | Handle<Object> result; |
| 206 | ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 207 | isolate, result, DefineClass(isolate, name, super_class, constructor, |
| 208 | start_position, end_position)); |
| 209 | return *result; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 210 | } |
| 211 | |
| 212 | |
| 213 | RUNTIME_FUNCTION(Runtime_DefineClassMethod) { |
| 214 | HandleScope scope(isolate); |
| 215 | DCHECK(args.length() == 3); |
| 216 | CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 217 | CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 218 | CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2); |
| 219 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 220 | RETURN_FAILURE_ON_EXCEPTION(isolate, |
| 221 | JSObject::DefinePropertyOrElementIgnoreAttributes( |
| 222 | object, name, function, DONT_ENUM)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 223 | return isolate->heap()->undefined_value(); |
| 224 | } |
| 225 | |
| 226 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 227 | RUNTIME_FUNCTION(Runtime_FinalizeClassDefinition) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 228 | HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 229 | DCHECK(args.length() == 2); |
| 230 | CONVERT_ARG_HANDLE_CHECKED(JSObject, constructor, 0); |
| 231 | CONVERT_ARG_HANDLE_CHECKED(JSObject, prototype, 1); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 232 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 233 | JSObject::MigrateSlowToFast(constructor, 0, "RuntimeToFastProperties"); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 234 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 235 | if (constructor->map()->is_strong()) { |
| 236 | DCHECK(prototype->map()->is_strong()); |
| 237 | MAYBE_RETURN(JSReceiver::SetIntegrityLevel(prototype, FROZEN, |
| 238 | Object::THROW_ON_ERROR), |
| 239 | isolate->heap()->exception()); |
| 240 | MAYBE_RETURN(JSReceiver::SetIntegrityLevel(constructor, FROZEN, |
| 241 | Object::THROW_ON_ERROR), |
| 242 | isolate->heap()->exception()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 243 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 244 | return *constructor; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 245 | } |
| 246 | |
| 247 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 248 | static MaybeHandle<Object> LoadFromSuper(Isolate* isolate, |
| 249 | Handle<Object> receiver, |
| 250 | Handle<JSObject> home_object, |
| 251 | Handle<Name> name, |
| 252 | LanguageMode language_mode) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 253 | if (home_object->IsAccessCheckNeeded() && |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 254 | !isolate->MayAccess(handle(isolate->context()), home_object)) { |
| 255 | isolate->ReportFailedAccessCheck(home_object); |
| 256 | RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | PrototypeIterator iter(isolate, home_object); |
| 260 | Handle<Object> proto = PrototypeIterator::GetCurrent(iter); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 261 | if (!proto->IsJSReceiver()) { |
| 262 | return Object::ReadAbsentProperty(isolate, proto, name, language_mode); |
| 263 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 264 | |
| 265 | LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto)); |
| 266 | Handle<Object> result; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 267 | ASSIGN_RETURN_ON_EXCEPTION(isolate, result, |
| 268 | Object::GetProperty(&it, language_mode), Object); |
| 269 | return result; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 273 | static MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate, |
| 274 | Handle<Object> receiver, |
| 275 | Handle<JSObject> home_object, |
| 276 | uint32_t index, |
| 277 | LanguageMode language_mode) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 278 | if (home_object->IsAccessCheckNeeded() && |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 279 | !isolate->MayAccess(handle(isolate->context()), home_object)) { |
| 280 | isolate->ReportFailedAccessCheck(home_object); |
| 281 | RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 282 | } |
| 283 | |
| 284 | PrototypeIterator iter(isolate, home_object); |
| 285 | Handle<Object> proto = PrototypeIterator::GetCurrent(iter); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 286 | if (!proto->IsJSReceiver()) { |
| 287 | Handle<Object> name = isolate->factory()->NewNumberFromUint(index); |
| 288 | return Object::ReadAbsentProperty(isolate, proto, name, language_mode); |
| 289 | } |
| 290 | |
| 291 | LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto)); |
| 292 | Handle<Object> result; |
| 293 | ASSIGN_RETURN_ON_EXCEPTION(isolate, result, |
| 294 | Object::GetProperty(&it, language_mode), Object); |
| 295 | return result; |
| 296 | } |
| 297 | |
| 298 | |
| 299 | // TODO(conradw): It would be more efficient to have a separate runtime function |
| 300 | // for strong mode. |
| 301 | RUNTIME_FUNCTION(Runtime_LoadFromSuper) { |
| 302 | HandleScope scope(isolate); |
| 303 | DCHECK(args.length() == 4); |
| 304 | CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
| 305 | CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1); |
| 306 | CONVERT_ARG_HANDLE_CHECKED(Name, name, 2); |
| 307 | CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 308 | |
| 309 | Handle<Object> result; |
| 310 | ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 311 | isolate, result, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 312 | LoadFromSuper(isolate, receiver, home_object, name, language_mode)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 313 | return *result; |
| 314 | } |
| 315 | |
| 316 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 317 | RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) { |
| 318 | HandleScope scope(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 319 | DCHECK(args.length() == 4); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 320 | CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
| 321 | CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1); |
| 322 | CONVERT_ARG_HANDLE_CHECKED(Object, key, 2); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 323 | CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 324 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 325 | uint32_t index = 0; |
| 326 | Handle<Object> result; |
| 327 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 328 | if (key->ToArrayIndex(&index)) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 329 | ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 330 | isolate, result, LoadElementFromSuper(isolate, receiver, home_object, |
| 331 | index, language_mode)); |
| 332 | return *result; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 333 | } |
| 334 | |
| 335 | Handle<Name> name; |
| 336 | ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 337 | Object::ToName(isolate, key)); |
| 338 | // TODO(verwaest): Unify using LookupIterator. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 339 | if (name->AsArrayIndex(&index)) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 340 | ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 341 | isolate, result, LoadElementFromSuper(isolate, receiver, home_object, |
| 342 | index, language_mode)); |
| 343 | return *result; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 344 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 345 | ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 346 | isolate, result, |
| 347 | LoadFromSuper(isolate, receiver, home_object, name, language_mode)); |
| 348 | return *result; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 349 | } |
| 350 | |
| 351 | |
| 352 | static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object, |
| 353 | Handle<Object> receiver, Handle<Name> name, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 354 | Handle<Object> value, LanguageMode language_mode) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 355 | if (home_object->IsAccessCheckNeeded() && |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 356 | !isolate->MayAccess(handle(isolate->context()), home_object)) { |
| 357 | isolate->ReportFailedAccessCheck(home_object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 358 | RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| 359 | } |
| 360 | |
| 361 | PrototypeIterator iter(isolate, home_object); |
| 362 | Handle<Object> proto = PrototypeIterator::GetCurrent(iter); |
| 363 | if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value(); |
| 364 | |
| 365 | LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 366 | MAYBE_RETURN(Object::SetSuperProperty(&it, value, language_mode, |
| 367 | Object::CERTAINLY_NOT_STORE_FROM_KEYED), |
| 368 | isolate->heap()->exception()); |
| 369 | return *value; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 370 | } |
| 371 | |
| 372 | |
| 373 | static Object* StoreElementToSuper(Isolate* isolate, |
| 374 | Handle<JSObject> home_object, |
| 375 | Handle<Object> receiver, uint32_t index, |
| 376 | Handle<Object> value, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 377 | LanguageMode language_mode) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 378 | if (home_object->IsAccessCheckNeeded() && |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 379 | !isolate->MayAccess(handle(isolate->context()), home_object)) { |
| 380 | isolate->ReportFailedAccessCheck(home_object); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 381 | RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| 382 | } |
| 383 | |
| 384 | PrototypeIterator iter(isolate, home_object); |
| 385 | Handle<Object> proto = PrototypeIterator::GetCurrent(iter); |
| 386 | if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value(); |
| 387 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 388 | LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto)); |
| 389 | MAYBE_RETURN(Object::SetSuperProperty(&it, value, language_mode, |
| 390 | Object::MAY_BE_STORE_FROM_KEYED), |
| 391 | isolate->heap()->exception()); |
| 392 | return *value; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 393 | } |
| 394 | |
| 395 | |
| 396 | RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) { |
| 397 | HandleScope scope(isolate); |
| 398 | DCHECK(args.length() == 4); |
| 399 | CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
| 400 | CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1); |
| 401 | CONVERT_ARG_HANDLE_CHECKED(Name, name, 2); |
| 402 | CONVERT_ARG_HANDLE_CHECKED(Object, value, 3); |
| 403 | |
| 404 | return StoreToSuper(isolate, home_object, receiver, name, value, STRICT); |
| 405 | } |
| 406 | |
| 407 | |
| 408 | RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) { |
| 409 | HandleScope scope(isolate); |
| 410 | DCHECK(args.length() == 4); |
| 411 | CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
| 412 | CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1); |
| 413 | CONVERT_ARG_HANDLE_CHECKED(Name, name, 2); |
| 414 | CONVERT_ARG_HANDLE_CHECKED(Object, value, 3); |
| 415 | |
| 416 | return StoreToSuper(isolate, home_object, receiver, name, value, SLOPPY); |
| 417 | } |
| 418 | |
| 419 | |
| 420 | static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object, |
| 421 | Handle<Object> receiver, Handle<Object> key, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 422 | Handle<Object> value, |
| 423 | LanguageMode language_mode) { |
| 424 | uint32_t index = 0; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 425 | |
| 426 | if (key->ToArrayIndex(&index)) { |
| 427 | return StoreElementToSuper(isolate, home_object, receiver, index, value, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 428 | language_mode); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 429 | } |
| 430 | Handle<Name> name; |
| 431 | ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 432 | Object::ToName(isolate, key)); |
| 433 | // TODO(verwaest): Unify using LookupIterator. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 434 | if (name->AsArrayIndex(&index)) { |
| 435 | return StoreElementToSuper(isolate, home_object, receiver, index, value, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 436 | language_mode); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 437 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 438 | return StoreToSuper(isolate, home_object, receiver, name, value, |
| 439 | language_mode); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 440 | } |
| 441 | |
| 442 | |
| 443 | RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Strict) { |
| 444 | HandleScope scope(isolate); |
| 445 | DCHECK(args.length() == 4); |
| 446 | CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
| 447 | CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1); |
| 448 | CONVERT_ARG_HANDLE_CHECKED(Object, key, 2); |
| 449 | CONVERT_ARG_HANDLE_CHECKED(Object, value, 3); |
| 450 | |
| 451 | return StoreKeyedToSuper(isolate, home_object, receiver, key, value, STRICT); |
| 452 | } |
| 453 | |
| 454 | |
| 455 | RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) { |
| 456 | HandleScope scope(isolate); |
| 457 | DCHECK(args.length() == 4); |
| 458 | CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
| 459 | CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1); |
| 460 | CONVERT_ARG_HANDLE_CHECKED(Object, key, 2); |
| 461 | CONVERT_ARG_HANDLE_CHECKED(Object, value, 3); |
| 462 | |
| 463 | return StoreKeyedToSuper(isolate, home_object, receiver, key, value, SLOPPY); |
| 464 | } |
| 465 | |
| 466 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 467 | RUNTIME_FUNCTION(Runtime_GetSuperConstructor) { |
| 468 | SealHandleScope shs(isolate); |
| 469 | DCHECK_EQ(1, args.length()); |
| 470 | CONVERT_ARG_CHECKED(JSFunction, active_function, 0); |
| 471 | return active_function->map()->prototype(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 472 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 473 | |
| 474 | } // namespace internal |
| 475 | } // namespace v8 |