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

Side by Side Diff: src/runtime.cc

Issue 132373011: A64: Synchronize with r17635. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/runtime.js » ('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 // 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 5013 matching lines...) Expand 10 before | Expand all | Expand 10 after
5024 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { 5024 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
5025 HandleScope scope(isolate); 5025 HandleScope scope(isolate);
5026 ASSERT(args.length() == 4); 5026 ASSERT(args.length() == 4);
5027 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); 5027 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
5028 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 5028 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5029 CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2); 5029 CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
5030 CONVERT_SMI_ARG_CHECKED(unchecked, 3); 5030 CONVERT_SMI_ARG_CHECKED(unchecked, 3);
5031 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); 5031 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5032 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); 5032 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5033 5033
5034 LookupResult result(isolate); 5034 LookupResult lookup(isolate);
5035 js_object->LocalLookupRealNamedProperty(*name, &result); 5035 js_object->LocalLookupRealNamedProperty(*name, &lookup);
5036 5036
5037 // Special case for callback properties. 5037 // Special case for callback properties.
5038 if (result.IsPropertyCallbacks()) { 5038 if (lookup.IsPropertyCallbacks()) {
5039 Object* callback = result.GetCallbackObject(); 5039 Handle<Object> callback(lookup.GetCallbackObject(), isolate);
5040 // To be compatible with Safari we do not change the value on API objects 5040 // To be compatible with Safari we do not change the value on API objects
5041 // in Object.defineProperty(). Firefox disagrees here, and actually changes 5041 // in Object.defineProperty(). Firefox disagrees here, and actually changes
5042 // the value. 5042 // the value.
5043 if (callback->IsAccessorInfo()) { 5043 if (callback->IsAccessorInfo()) {
5044 return isolate->heap()->undefined_value(); 5044 return isolate->heap()->undefined_value();
5045 } 5045 }
5046 // Avoid redefining foreign callback as data property, just use the stored 5046 // Avoid redefining foreign callback as data property, just use the stored
5047 // setter to update the value instead. 5047 // setter to update the value instead.
5048 // TODO(mstarzinger): So far this only works if property attributes don't 5048 // TODO(mstarzinger): So far this only works if property attributes don't
5049 // change, this should be fixed once we cleanup the underlying code. 5049 // change, this should be fixed once we cleanup the underlying code.
5050 if (callback->IsForeign() && result.GetAttributes() == attr) { 5050 if (callback->IsForeign() && lookup.GetAttributes() == attr) {
5051 Handle<Object> result_object = 5051 Handle<Object> result_object =
5052 JSObject::SetPropertyWithCallback(js_object, 5052 JSObject::SetPropertyWithCallback(js_object,
5053 handle(callback, isolate), 5053 callback,
5054 name, 5054 name,
5055 obj_value, 5055 obj_value,
5056 handle(result.holder()), 5056 handle(lookup.holder()),
5057 kStrictMode); 5057 kStrictMode);
5058 RETURN_IF_EMPTY_HANDLE(isolate, result_object); 5058 RETURN_IF_EMPTY_HANDLE(isolate, result_object);
5059 return *result_object; 5059 return *result_object;
5060 } 5060 }
5061 } 5061 }
5062 5062
5063 // Take special care when attributes are different and there is already 5063 // Take special care when attributes are different and there is already
5064 // a property. For simplicity we normalize the property which enables us 5064 // a property. For simplicity we normalize the property which enables us
5065 // to not worry about changing the instance_descriptor and creating a new 5065 // to not worry about changing the instance_descriptor and creating a new
5066 // map. The current version of SetObjectProperty does not handle attributes 5066 // map. The current version of SetObjectProperty does not handle attributes
5067 // correctly in the case where a property is a field and is reset with 5067 // correctly in the case where a property is a field and is reset with
5068 // new attributes. 5068 // new attributes.
5069 if (result.IsFound() && 5069 if (lookup.IsFound() &&
5070 (attr != result.GetAttributes() || result.IsPropertyCallbacks())) { 5070 (attr != lookup.GetAttributes() || lookup.IsPropertyCallbacks())) {
5071 // New attributes - normalize to avoid writing to instance descriptor 5071 // New attributes - normalize to avoid writing to instance descriptor
5072 if (js_object->IsJSGlobalProxy()) { 5072 if (js_object->IsJSGlobalProxy()) {
5073 // Since the result is a property, the prototype will exist so 5073 // Since the result is a property, the prototype will exist so
5074 // we don't have to check for null. 5074 // we don't have to check for null.
5075 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); 5075 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
5076 } 5076 }
5077 JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); 5077 JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
5078 // Use IgnoreAttributes version since a readonly property may be 5078 // Use IgnoreAttributes version since a readonly property may be
5079 // overridden and SetProperty does not allow this. 5079 // overridden and SetProperty does not allow this.
5080 Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( 5080 Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5081 js_object, name, obj_value, attr); 5081 js_object, name, obj_value, attr);
5082 RETURN_IF_EMPTY_HANDLE(isolate, result); 5082 RETURN_IF_EMPTY_HANDLE(isolate, result);
5083 return *result; 5083 return *result;
5084 } 5084 }
5085 5085
5086 return Runtime::ForceSetObjectProperty(isolate, 5086 Handle<Object> result = Runtime::ForceSetObjectProperty(isolate, js_object,
5087 js_object, 5087 name,
5088 name, 5088 obj_value,
5089 obj_value, 5089 attr);
5090 attr); 5090 RETURN_IF_EMPTY_HANDLE(isolate, result);
5091 return *result;
5091 } 5092 }
5092 5093
5093 5094
5094 // Return property without being observable by accessors or interceptors. 5095 // Return property without being observable by accessors or interceptors.
5095 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) { 5096 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
5096 SealHandleScope shs(isolate); 5097 SealHandleScope shs(isolate);
5097 ASSERT(args.length() == 2); 5098 ASSERT(args.length() == 2);
5098 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 5099 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5099 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); 5100 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5100 LookupResult lookup(isolate); 5101 LookupResult lookup(isolate);
(...skipping 13 matching lines...) Expand all
5114 case INTERCEPTOR: 5115 case INTERCEPTOR:
5115 case TRANSITION: 5116 case TRANSITION:
5116 return isolate->heap()->undefined_value(); 5117 return isolate->heap()->undefined_value();
5117 case NONEXISTENT: 5118 case NONEXISTENT:
5118 UNREACHABLE(); 5119 UNREACHABLE();
5119 } 5120 }
5120 return isolate->heap()->undefined_value(); 5121 return isolate->heap()->undefined_value();
5121 } 5122 }
5122 5123
5123 5124
5124 MaybeObject* Runtime::SetObjectPropertyOrFail( 5125 Handle<Object> Runtime::SetObjectProperty(Isolate* isolate,
5125 Isolate* isolate, 5126 Handle<Object> object,
5126 Handle<Object> object, 5127 Handle<Object> key,
5127 Handle<Object> key, 5128 Handle<Object> value,
5128 Handle<Object> value, 5129 PropertyAttributes attr,
5129 PropertyAttributes attr, 5130 StrictModeFlag strict_mode) {
5130 StrictModeFlag strict_mode) {
5131 CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
5132 SetObjectProperty(isolate, object, key, value, attr, strict_mode));
5133 }
5134
5135
5136 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
5137 Handle<Object> object,
5138 Handle<Object> key,
5139 Handle<Object> value,
5140 PropertyAttributes attr,
5141 StrictModeFlag strict_mode) {
5142 SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY; 5131 SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
5143 HandleScope scope(isolate);
5144 5132
5145 if (object->IsUndefined() || object->IsNull()) { 5133 if (object->IsUndefined() || object->IsNull()) {
5146 Handle<Object> args[2] = { key, object }; 5134 Handle<Object> args[2] = { key, object };
5147 Handle<Object> error = 5135 Handle<Object> error =
5148 isolate->factory()->NewTypeError("non_object_property_store", 5136 isolate->factory()->NewTypeError("non_object_property_store",
5149 HandleVector(args, 2)); 5137 HandleVector(args, 2));
5150 return isolate->Throw(*error); 5138 isolate->Throw(*error);
5139 return Handle<Object>();
5151 } 5140 }
5152 5141
5153 if (object->IsJSProxy()) { 5142 if (object->IsJSProxy()) {
5154 bool has_pending_exception = false; 5143 bool has_pending_exception = false;
5155 Handle<Object> name_object = key->IsSymbol() 5144 Handle<Object> name_object = key->IsSymbol()
5156 ? key : Execution::ToString(isolate, key, &has_pending_exception); 5145 ? key : Execution::ToString(isolate, key, &has_pending_exception);
5157 if (has_pending_exception) return Failure::Exception(); 5146 if (has_pending_exception) return Handle<Object>(); // exception
5158 Handle<Name> name = Handle<Name>::cast(name_object); 5147 Handle<Name> name = Handle<Name>::cast(name_object);
5159 Handle<Object> result = JSReceiver::SetProperty( 5148 return JSReceiver::SetProperty(Handle<JSProxy>::cast(object), name, value,
5160 Handle<JSProxy>::cast(object), name, value, attr, strict_mode); 5149 attr,
5161 RETURN_IF_EMPTY_HANDLE(isolate, result); 5150 strict_mode);
5162 return *result;
5163 } 5151 }
5164 5152
5165 // If the object isn't a JavaScript object, we ignore the store. 5153 // If the object isn't a JavaScript object, we ignore the store.
5166 if (!object->IsJSObject()) return *value; 5154 if (!object->IsJSObject()) return value;
5167 5155
5168 Handle<JSObject> js_object = Handle<JSObject>::cast(object); 5156 Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5169 5157
5170 // Check if the given key is an array index. 5158 // Check if the given key is an array index.
5171 uint32_t index; 5159 uint32_t index;
5172 if (key->ToArrayIndex(&index)) { 5160 if (key->ToArrayIndex(&index)) {
5173 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters 5161 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5174 // of a string using [] notation. We need to support this too in 5162 // of a string using [] notation. We need to support this too in
5175 // JavaScript. 5163 // JavaScript.
5176 // In the case of a String object we just need to redirect the assignment to 5164 // In the case of a String object we just need to redirect the assignment to
5177 // the underlying string if the index is in range. Since the underlying 5165 // the underlying string if the index is in range. Since the underlying
5178 // string does nothing with the assignment then we can ignore such 5166 // string does nothing with the assignment then we can ignore such
5179 // assignments. 5167 // assignments.
5180 if (js_object->IsStringObjectWithCharacterAt(index)) { 5168 if (js_object->IsStringObjectWithCharacterAt(index)) {
5181 return *value; 5169 return value;
5182 } 5170 }
5183 5171
5184 js_object->ValidateElements(); 5172 js_object->ValidateElements();
5185 if (js_object->HasExternalArrayElements()) { 5173 if (js_object->HasExternalArrayElements()) {
5186 if (!value->IsNumber() && !value->IsUndefined()) { 5174 if (!value->IsNumber() && !value->IsUndefined()) {
5187 bool has_exception; 5175 bool has_exception;
5188 Handle<Object> number = 5176 Handle<Object> number =
5189 Execution::ToNumber(isolate, value, &has_exception); 5177 Execution::ToNumber(isolate, value, &has_exception);
5190 if (has_exception) return Failure::Exception(); 5178 if (has_exception) return Handle<Object>(); // exception
5191 value = number; 5179 value = number;
5192 } 5180 }
5193 } 5181 }
5194 MaybeObject* result = js_object->SetElement( 5182 Handle<Object> result = JSObject::SetElement(js_object, index, value, attr,
5195 index, *value, attr, strict_mode, true, set_mode); 5183 strict_mode,
5184 true,
5185 set_mode);
5196 js_object->ValidateElements(); 5186 js_object->ValidateElements();
5197 if (result->IsFailure()) return result; 5187 return result.is_null() ? result : value;
5198 return *value;
5199 } 5188 }
5200 5189
5201 if (key->IsName()) { 5190 if (key->IsName()) {
5202 Handle<Name> name = Handle<Name>::cast(key); 5191 Handle<Name> name = Handle<Name>::cast(key);
5203 if (name->AsArrayIndex(&index)) { 5192 if (name->AsArrayIndex(&index)) {
5204 if (js_object->HasExternalArrayElements()) { 5193 if (js_object->HasExternalArrayElements()) {
5205 if (!value->IsNumber() && !value->IsUndefined()) { 5194 if (!value->IsNumber() && !value->IsUndefined()) {
5206 bool has_exception; 5195 bool has_exception;
5207 Handle<Object> number = 5196 Handle<Object> number =
5208 Execution::ToNumber(isolate, value, &has_exception); 5197 Execution::ToNumber(isolate, value, &has_exception);
5209 if (has_exception) return Failure::Exception(); 5198 if (has_exception) return Handle<Object>(); // exception
5210 value = number; 5199 value = number;
5211 } 5200 }
5212 } 5201 }
5213 MaybeObject* result = js_object->SetElement( 5202 return JSObject::SetElement(js_object, index, value, attr, strict_mode,
5214 index, *value, attr, strict_mode, true, set_mode); 5203 true,
5215 if (result->IsFailure()) return result; 5204 set_mode);
5216 } else { 5205 } else {
5217 if (name->IsString()) Handle<String>::cast(name)->TryFlatten(); 5206 if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5218 Handle<Object> result = 5207 return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5219 JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5220 RETURN_IF_EMPTY_HANDLE(isolate, result);
5221 } 5208 }
5222 return *value;
5223 } 5209 }
5224 5210
5225 // Call-back into JavaScript to convert the key to a string. 5211 // Call-back into JavaScript to convert the key to a string.
5226 bool has_pending_exception = false; 5212 bool has_pending_exception = false;
5227 Handle<Object> converted = 5213 Handle<Object> converted =
5228 Execution::ToString(isolate, key, &has_pending_exception); 5214 Execution::ToString(isolate, key, &has_pending_exception);
5229 if (has_pending_exception) return Failure::Exception(); 5215 if (has_pending_exception) return Handle<Object>(); // exception
5230 Handle<String> name = Handle<String>::cast(converted); 5216 Handle<String> name = Handle<String>::cast(converted);
5231 5217
5232 if (name->AsArrayIndex(&index)) { 5218 if (name->AsArrayIndex(&index)) {
5233 return js_object->SetElement( 5219 return JSObject::SetElement(js_object, index, value, attr, strict_mode,
5234 index, *value, attr, strict_mode, true, set_mode); 5220 true,
5221 set_mode);
5235 } else { 5222 } else {
5236 Handle<Object> result = 5223 return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5237 JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5238 RETURN_IF_EMPTY_HANDLE(isolate, result);
5239 return *result;
5240 } 5224 }
5241 } 5225 }
5242 5226
5243 5227
5244 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, 5228 Handle<Object> Runtime::ForceSetObjectProperty(Isolate* isolate,
5245 Handle<JSObject> js_object, 5229 Handle<JSObject> js_object,
5246 Handle<Object> key, 5230 Handle<Object> key,
5247 Handle<Object> value, 5231 Handle<Object> value,
5248 PropertyAttributes attr) { 5232 PropertyAttributes attr) {
5249 HandleScope scope(isolate);
5250
5251 // Check if the given key is an array index. 5233 // Check if the given key is an array index.
5252 uint32_t index; 5234 uint32_t index;
5253 if (key->ToArrayIndex(&index)) { 5235 if (key->ToArrayIndex(&index)) {
5254 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters 5236 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5255 // of a string using [] notation. We need to support this too in 5237 // of a string using [] notation. We need to support this too in
5256 // JavaScript. 5238 // JavaScript.
5257 // In the case of a String object we just need to redirect the assignment to 5239 // In the case of a String object we just need to redirect the assignment to
5258 // the underlying string if the index is in range. Since the underlying 5240 // the underlying string if the index is in range. Since the underlying
5259 // string does nothing with the assignment then we can ignore such 5241 // string does nothing with the assignment then we can ignore such
5260 // assignments. 5242 // assignments.
5261 if (js_object->IsStringObjectWithCharacterAt(index)) { 5243 if (js_object->IsStringObjectWithCharacterAt(index)) {
5262 return *value; 5244 return value;
5263 } 5245 }
5264 5246
5265 return js_object->SetElement( 5247 return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
5266 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); 5248 false,
5249 DEFINE_PROPERTY);
5267 } 5250 }
5268 5251
5269 if (key->IsName()) { 5252 if (key->IsName()) {
5270 Handle<Name> name = Handle<Name>::cast(key); 5253 Handle<Name> name = Handle<Name>::cast(key);
5271 if (name->AsArrayIndex(&index)) { 5254 if (name->AsArrayIndex(&index)) {
5272 return js_object->SetElement( 5255 return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
5273 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); 5256 false,
5257 DEFINE_PROPERTY);
5274 } else { 5258 } else {
5275 if (name->IsString()) Handle<String>::cast(name)->TryFlatten(); 5259 if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5276 Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( 5260 return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name,
5277 js_object, name, value, attr); 5261 value, attr);
5278 RETURN_IF_EMPTY_HANDLE(isolate, result);
5279 return *result;
5280 } 5262 }
5281 } 5263 }
5282 5264
5283 // Call-back into JavaScript to convert the key to a string. 5265 // Call-back into JavaScript to convert the key to a string.
5284 bool has_pending_exception = false; 5266 bool has_pending_exception = false;
5285 Handle<Object> converted = 5267 Handle<Object> converted =
5286 Execution::ToString(isolate, key, &has_pending_exception); 5268 Execution::ToString(isolate, key, &has_pending_exception);
5287 if (has_pending_exception) return Failure::Exception(); 5269 if (has_pending_exception) return Handle<Object>(); // exception
5288 Handle<String> name = Handle<String>::cast(converted); 5270 Handle<String> name = Handle<String>::cast(converted);
5289 5271
5290 if (name->AsArrayIndex(&index)) { 5272 if (name->AsArrayIndex(&index)) {
5291 return js_object->SetElement( 5273 return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
5292 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); 5274 false,
5275 DEFINE_PROPERTY);
5293 } else { 5276 } else {
5294 Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( 5277 return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name, value,
5295 js_object, name, value, attr); 5278 attr);
5296 RETURN_IF_EMPTY_HANDLE(isolate, result);
5297 return *result;
5298 } 5279 }
5299 } 5280 }
5300 5281
5301 5282
5302 MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate, 5283 MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
5303 Handle<JSReceiver> receiver, 5284 Handle<JSReceiver> receiver,
5304 Handle<Object> key, 5285 Handle<Object> key,
5305 JSReceiver::DeleteMode mode) { 5286 JSReceiver::DeleteMode mode) {
5306 HandleScope scope(isolate); 5287 HandleScope scope(isolate);
5307 5288
(...skipping 28 matching lines...) Expand all
5336 } 5317 }
5337 5318
5338 if (name->IsString()) Handle<String>::cast(name)->TryFlatten(); 5319 if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5339 Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode); 5320 Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
5340 RETURN_IF_EMPTY_HANDLE(isolate, result); 5321 RETURN_IF_EMPTY_HANDLE(isolate, result);
5341 return *result; 5322 return *result;
5342 } 5323 }
5343 5324
5344 5325
5345 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) { 5326 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
5346 SealHandleScope shs(isolate); 5327 HandleScope scope(isolate);
5347 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5); 5328 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5348 5329
5349 Handle<Object> object = args.at<Object>(0); 5330 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5350 Handle<Object> key = args.at<Object>(1); 5331 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
5351 Handle<Object> value = args.at<Object>(2); 5332 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5352 CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3); 5333 CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5353 RUNTIME_ASSERT( 5334 RUNTIME_ASSERT(
5354 (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); 5335 (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5355 // Compute attributes. 5336 // Compute attributes.
5356 PropertyAttributes attributes = 5337 PropertyAttributes attributes =
5357 static_cast<PropertyAttributes>(unchecked_attributes); 5338 static_cast<PropertyAttributes>(unchecked_attributes);
5358 5339
5359 StrictModeFlag strict_mode = kNonStrictMode; 5340 StrictModeFlag strict_mode = kNonStrictMode;
5360 if (args.length() == 5) { 5341 if (args.length() == 5) {
5361 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4); 5342 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
5362 strict_mode = strict_mode_flag; 5343 strict_mode = strict_mode_flag;
5363 } 5344 }
5364 5345
5365 return Runtime::SetObjectProperty(isolate, 5346 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
5366 object, 5347 value,
5367 key, 5348 attributes,
5368 value, 5349 strict_mode);
5369 attributes, 5350 RETURN_IF_EMPTY_HANDLE(isolate, result);
5370 strict_mode); 5351 return *result;
5371 } 5352 }
5372 5353
5373 5354
5374 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) { 5355 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
5375 HandleScope scope(isolate); 5356 HandleScope scope(isolate);
5376 RUNTIME_ASSERT(args.length() == 2); 5357 RUNTIME_ASSERT(args.length() == 2);
5377 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); 5358 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
5378 CONVERT_ARG_HANDLE_CHECKED(Map, map, 1); 5359 CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
5379 JSObject::TransitionElementsKind(array, map->elements_kind()); 5360 JSObject::TransitionElementsKind(array, map->elements_kind());
5380 return *array; 5361 return *array;
5381 } 5362 }
5382 5363
5383 5364
5384 // Set the native flag on the function. 5365 // Set the native flag on the function.
5385 // This is used to decide if we should transform null and undefined 5366 // This is used to decide if we should transform null and undefined
5386 // into the global object when doing call and apply. 5367 // into the global object when doing call and apply.
5387 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) { 5368 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
5388 SealHandleScope shs(isolate); 5369 SealHandleScope shs(isolate);
5389 RUNTIME_ASSERT(args.length() == 1); 5370 RUNTIME_ASSERT(args.length() == 1);
5390 5371
5391 Handle<Object> object = args.at<Object>(0); 5372 CONVERT_ARG_CHECKED(Object, object, 0);
5392 5373
5393 if (object->IsJSFunction()) { 5374 if (object->IsJSFunction()) {
5394 JSFunction* func = JSFunction::cast(*object); 5375 JSFunction* func = JSFunction::cast(object);
5395 func->shared()->set_native(true); 5376 func->shared()->set_native(true);
5396 } 5377 }
5397 return isolate->heap()->undefined_value(); 5378 return isolate->heap()->undefined_value();
5398 } 5379 }
5399 5380
5400 5381
5401 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) { 5382 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
5402 HandleScope scope(isolate); 5383 HandleScope scope(isolate);
5403 RUNTIME_ASSERT(args.length() == 5); 5384 RUNTIME_ASSERT(args.length() == 5);
5404 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 5385 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after
6187 6168
6188 // Create a number object from the value. 6169 // Create a number object from the value.
6189 return isolate->heap()->NumberFromDouble(value); 6170 return isolate->heap()->NumberFromDouble(value);
6190 } 6171 }
6191 6172
6192 6173
6193 template <class Converter> 6174 template <class Converter>
6194 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper( 6175 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6195 Isolate* isolate, 6176 Isolate* isolate,
6196 String* s, 6177 String* s,
6178 String::Encoding result_encoding,
6197 int length, 6179 int length,
6198 int input_string_length, 6180 int input_string_length,
6199 unibrow::Mapping<Converter, 128>* mapping) { 6181 unibrow::Mapping<Converter, 128>* mapping) {
6200 // We try this twice, once with the assumption that the result is no longer 6182 // We try this twice, once with the assumption that the result is no longer
6201 // than the input and, if that assumption breaks, again with the exact 6183 // than the input and, if that assumption breaks, again with the exact
6202 // length. This may not be pretty, but it is nicer than what was here before 6184 // length. This may not be pretty, but it is nicer than what was here before
6203 // and I hereby claim my vaffel-is. 6185 // and I hereby claim my vaffel-is.
6204 // 6186 //
6205 // Allocate the resulting string. 6187 // Allocate the resulting string.
6206 // 6188 //
6207 // NOTE: This assumes that the upper/lower case of an ASCII 6189 // NOTE: This assumes that the upper/lower case of an ASCII
6208 // character is also ASCII. This is currently the case, but it 6190 // character is also ASCII. This is currently the case, but it
6209 // might break in the future if we implement more context and locale 6191 // might break in the future if we implement more context and locale
6210 // dependent upper/lower conversions. 6192 // dependent upper/lower conversions.
6211 Object* o; 6193 Object* o;
6212 { MaybeObject* maybe_o = s->IsOneByteRepresentation() 6194 { MaybeObject* maybe_o = result_encoding == String::ONE_BYTE_ENCODING
6213 ? isolate->heap()->AllocateRawOneByteString(length) 6195 ? isolate->heap()->AllocateRawOneByteString(length)
6214 : isolate->heap()->AllocateRawTwoByteString(length); 6196 : isolate->heap()->AllocateRawTwoByteString(length);
6215 if (!maybe_o->ToObject(&o)) return maybe_o; 6197 if (!maybe_o->ToObject(&o)) return maybe_o;
6216 } 6198 }
6217 String* result = String::cast(o); 6199 String* result = String::cast(o);
6218 bool has_changed_character = false; 6200 bool has_changed_character = false;
6219 6201
6202 DisallowHeapAllocation no_gc;
6203
6220 // Convert all characters to upper case, assuming that they will fit 6204 // Convert all characters to upper case, assuming that they will fit
6221 // in the buffer 6205 // in the buffer
6222 Access<ConsStringIteratorOp> op( 6206 Access<ConsStringIteratorOp> op(
6223 isolate->runtime_state()->string_iterator()); 6207 isolate->runtime_state()->string_iterator());
6224 StringCharacterStream stream(s, op.value()); 6208 StringCharacterStream stream(s, op.value());
6225 unibrow::uchar chars[Converter::kMaxWidth]; 6209 unibrow::uchar chars[Converter::kMaxWidth];
6226 // We can assume that the string is not empty 6210 // We can assume that the string is not empty
6227 uc32 current = stream.GetNext(); 6211 uc32 current = stream.GetNext();
6212 // y with umlauts is the only character that stops fitting into one-byte
6213 // when converting to uppercase.
6214 static const uc32 yuml_code = 0xff;
6215 bool ignore_yuml = result->IsSeqTwoByteString() || Converter::kIsToLower;
6228 for (int i = 0; i < length;) { 6216 for (int i = 0; i < length;) {
6229 bool has_next = stream.HasMore(); 6217 bool has_next = stream.HasMore();
6230 uc32 next = has_next ? stream.GetNext() : 0; 6218 uc32 next = has_next ? stream.GetNext() : 0;
6231 int char_length = mapping->get(current, next, chars); 6219 int char_length = mapping->get(current, next, chars);
6232 if (char_length == 0) { 6220 if (char_length == 0) {
6233 // The case conversion of this character is the character itself. 6221 // The case conversion of this character is the character itself.
6234 result->Set(i, current); 6222 result->Set(i, current);
6235 i++; 6223 i++;
6236 } else if (char_length == 1) { 6224 } else if (char_length == 1 && (ignore_yuml || current != yuml_code)) {
6237 // Common case: converting the letter resulted in one character. 6225 // Common case: converting the letter resulted in one character.
6238 ASSERT(static_cast<uc32>(chars[0]) != current); 6226 ASSERT(static_cast<uc32>(chars[0]) != current);
6239 result->Set(i, chars[0]); 6227 result->Set(i, chars[0]);
6240 has_changed_character = true; 6228 has_changed_character = true;
6241 i++; 6229 i++;
6242 } else if (length == input_string_length) { 6230 } else if (length == input_string_length) {
6231 bool found_yuml = (current == yuml_code);
6243 // We've assumed that the result would be as long as the 6232 // We've assumed that the result would be as long as the
6244 // input but here is a character that converts to several 6233 // input but here is a character that converts to several
6245 // characters. No matter, we calculate the exact length 6234 // characters. No matter, we calculate the exact length
6246 // of the result and try the whole thing again. 6235 // of the result and try the whole thing again.
6247 // 6236 //
6248 // Note that this leaves room for optimization. We could just 6237 // Note that this leaves room for optimization. We could just
6249 // memcpy what we already have to the result string. Also, 6238 // memcpy what we already have to the result string. Also,
6250 // the result string is the last object allocated we could 6239 // the result string is the last object allocated we could
6251 // "realloc" it and probably, in the vast majority of cases, 6240 // "realloc" it and probably, in the vast majority of cases,
6252 // extend the existing string to be able to hold the full 6241 // extend the existing string to be able to hold the full
6253 // result. 6242 // result.
6254 int next_length = 0; 6243 int next_length = 0;
6255 if (has_next) { 6244 if (has_next) {
6256 next_length = mapping->get(next, 0, chars); 6245 next_length = mapping->get(next, 0, chars);
6257 if (next_length == 0) next_length = 1; 6246 if (next_length == 0) next_length = 1;
6258 } 6247 }
6259 int current_length = i + char_length + next_length; 6248 int current_length = i + char_length + next_length;
6260 while (stream.HasMore()) { 6249 while (stream.HasMore()) {
6261 current = stream.GetNext(); 6250 current = stream.GetNext();
6251 found_yuml |= (current == yuml_code);
6262 // NOTE: we use 0 as the next character here because, while 6252 // NOTE: we use 0 as the next character here because, while
6263 // the next character may affect what a character converts to, 6253 // the next character may affect what a character converts to,
6264 // it does not in any case affect the length of what it convert 6254 // it does not in any case affect the length of what it convert
6265 // to. 6255 // to.
6266 int char_length = mapping->get(current, 0, chars); 6256 int char_length = mapping->get(current, 0, chars);
6267 if (char_length == 0) char_length = 1; 6257 if (char_length == 0) char_length = 1;
6268 current_length += char_length; 6258 current_length += char_length;
6269 if (current_length > Smi::kMaxValue) { 6259 if (current_length > Smi::kMaxValue) {
6270 isolate->context()->mark_out_of_memory(); 6260 isolate->context()->mark_out_of_memory();
6271 return Failure::OutOfMemoryException(0x13); 6261 return Failure::OutOfMemoryException(0x13);
6272 } 6262 }
6273 } 6263 }
6274 // Try again with the real length. 6264 // Try again with the real length. Return signed if we need
6275 return Smi::FromInt(current_length); 6265 // to allocate a two-byte string for y-umlaut to uppercase.
6266 return (found_yuml && !ignore_yuml) ? Smi::FromInt(-current_length)
6267 : Smi::FromInt(current_length);
6276 } else { 6268 } else {
6277 for (int j = 0; j < char_length; j++) { 6269 for (int j = 0; j < char_length; j++) {
6278 result->Set(i, chars[j]); 6270 result->Set(i, chars[j]);
6279 i++; 6271 i++;
6280 } 6272 }
6281 has_changed_character = true; 6273 has_changed_character = true;
6282 } 6274 }
6283 current = next; 6275 current = next;
6284 } 6276 }
6285 if (has_changed_character) { 6277 if (has_changed_character) {
(...skipping 25 matching lines...) Expand all
6311 // further simplified. 6303 // further simplified.
6312 ASSERT(0 < m && m < n); 6304 ASSERT(0 < m && m < n);
6313 // Has high bit set in every w byte less than n. 6305 // Has high bit set in every w byte less than n.
6314 uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w; 6306 uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6315 // Has high bit set in every w byte greater than m. 6307 // Has high bit set in every w byte greater than m.
6316 uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m); 6308 uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6317 return (tmp1 & tmp2 & (kOneInEveryByte * 0x80)); 6309 return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6318 } 6310 }
6319 6311
6320 6312
6321 enum AsciiCaseConversion { 6313 #ifdef DEBUG
6322 ASCII_TO_LOWER, 6314 static bool CheckFastAsciiConvert(char* dst,
6323 ASCII_TO_UPPER 6315 char* src,
6324 }; 6316 int length,
6317 bool changed,
6318 bool is_to_lower) {
6319 bool expected_changed = false;
6320 for (int i = 0; i < length; i++) {
6321 if (dst[i] == src[i]) continue;
6322 expected_changed = true;
6323 if (is_to_lower) {
6324 ASSERT('A' <= src[i] && src[i] <= 'Z');
6325 ASSERT(dst[i] == src[i] + ('a' - 'A'));
6326 } else {
6327 ASSERT('a' <= src[i] && src[i] <= 'z');
6328 ASSERT(dst[i] == src[i] - ('a' - 'A'));
6329 }
6330 }
6331 return (expected_changed == changed);
6332 }
6333 #endif
6325 6334
6326 6335
6327 template <AsciiCaseConversion dir> 6336 template<class Converter>
6328 struct FastAsciiConverter { 6337 static bool FastAsciiConvert(char* dst,
6329 static bool Convert(char* dst, char* src, int length, bool* changed_out) { 6338 char* src,
6339 int length,
6340 bool* changed_out) {
6330 #ifdef DEBUG 6341 #ifdef DEBUG
6331 char* saved_dst = dst; 6342 char* saved_dst = dst;
6332 char* saved_src = src; 6343 char* saved_src = src;
6333 #endif 6344 #endif
6334 // We rely on the distance between upper and lower case letters 6345 DisallowHeapAllocation no_gc;
6335 // being a known power of 2. 6346 // We rely on the distance between upper and lower case letters
6336 ASSERT('a' - 'A' == (1 << 5)); 6347 // being a known power of 2.
6337 // Boundaries for the range of input characters than require conversion. 6348 ASSERT('a' - 'A' == (1 << 5));
6338 const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1; 6349 // Boundaries for the range of input characters than require conversion.
6339 const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1; 6350 static const char lo = Converter::kIsToLower ? 'A' - 1 : 'a' - 1;
6340 bool changed = false; 6351 static const char hi = Converter::kIsToLower ? 'Z' + 1 : 'z' + 1;
6341 uintptr_t or_acc = 0; 6352 bool changed = false;
6342 char* const limit = src + length; 6353 uintptr_t or_acc = 0;
6354 char* const limit = src + length;
6343 #ifdef V8_HOST_CAN_READ_UNALIGNED 6355 #ifdef V8_HOST_CAN_READ_UNALIGNED
6344 // Process the prefix of the input that requires no conversion one 6356 // Process the prefix of the input that requires no conversion one
6345 // (machine) word at a time. 6357 // (machine) word at a time.
6346 while (src <= limit - sizeof(uintptr_t)) { 6358 while (src <= limit - sizeof(uintptr_t)) {
6347 uintptr_t w = *reinterpret_cast<uintptr_t*>(src); 6359 uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6348 or_acc |= w; 6360 or_acc |= w;
6349 if (AsciiRangeMask(w, lo, hi) != 0) { 6361 if (AsciiRangeMask(w, lo, hi) != 0) {
6350 changed = true; 6362 changed = true;
6351 break; 6363 break;
6352 }
6353 *reinterpret_cast<uintptr_t*>(dst) = w;
6354 src += sizeof(uintptr_t);
6355 dst += sizeof(uintptr_t);
6356 } 6364 }
6357 // Process the remainder of the input performing conversion when 6365 *reinterpret_cast<uintptr_t*>(dst) = w;
6358 // required one word at a time. 6366 src += sizeof(uintptr_t);
6359 while (src <= limit - sizeof(uintptr_t)) { 6367 dst += sizeof(uintptr_t);
6360 uintptr_t w = *reinterpret_cast<uintptr_t*>(src); 6368 }
6361 or_acc |= w; 6369 // Process the remainder of the input performing conversion when
6362 uintptr_t m = AsciiRangeMask(w, lo, hi); 6370 // required one word at a time.
6363 // The mask has high (7th) bit set in every byte that needs 6371 while (src <= limit - sizeof(uintptr_t)) {
6364 // conversion and we know that the distance between cases is 6372 uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6365 // 1 << 5. 6373 or_acc |= w;
6366 *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2); 6374 uintptr_t m = AsciiRangeMask(w, lo, hi);
6367 src += sizeof(uintptr_t); 6375 // The mask has high (7th) bit set in every byte that needs
6368 dst += sizeof(uintptr_t); 6376 // conversion and we know that the distance between cases is
6377 // 1 << 5.
6378 *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6379 src += sizeof(uintptr_t);
6380 dst += sizeof(uintptr_t);
6381 }
6382 #endif
6383 // Process the last few bytes of the input (or the whole input if
6384 // unaligned access is not supported).
6385 while (src < limit) {
6386 char c = *src;
6387 or_acc |= c;
6388 if (lo < c && c < hi) {
6389 c ^= (1 << 5);
6390 changed = true;
6369 } 6391 }
6370 #endif 6392 *dst = c;
6371 // Process the last few bytes of the input (or the whole input if 6393 ++src;
6372 // unaligned access is not supported). 6394 ++dst;
6373 while (src < limit) { 6395 }
6374 char c = *src; 6396 if ((or_acc & kAsciiMask) != 0) {
6375 or_acc |= c; 6397 return false;
6376 if (lo < c && c < hi) {
6377 c ^= (1 << 5);
6378 changed = true;
6379 }
6380 *dst = c;
6381 ++src;
6382 ++dst;
6383 }
6384 if ((or_acc & kAsciiMask) != 0) {
6385 return false;
6386 }
6387 #ifdef DEBUG
6388 CheckConvert(saved_dst, saved_src, length, changed);
6389 #endif
6390 *changed_out = changed;
6391 return true;
6392 } 6398 }
6393 6399
6394 #ifdef DEBUG 6400 ASSERT(CheckFastAsciiConvert(
6395 static void CheckConvert(char* dst, char* src, int length, bool changed) { 6401 saved_dst, saved_src, length, changed, Converter::kIsToLower));
6396 bool expected_changed = false;
6397 for (int i = 0; i < length; i++) {
6398 if (dst[i] == src[i]) continue;
6399 expected_changed = true;
6400 if (dir == ASCII_TO_LOWER) {
6401 ASSERT('A' <= src[i] && src[i] <= 'Z');
6402 ASSERT(dst[i] == src[i] + ('a' - 'A'));
6403 } else {
6404 ASSERT(dir == ASCII_TO_UPPER);
6405 ASSERT('a' <= src[i] && src[i] <= 'z');
6406 ASSERT(dst[i] == src[i] - ('a' - 'A'));
6407 }
6408 }
6409 ASSERT(expected_changed == changed);
6410 }
6411 #endif
6412 };
6413 6402
6414 6403 *changed_out = changed;
6415 struct ToLowerTraits { 6404 return true;
6416 typedef unibrow::ToLowercase UnibrowConverter; 6405 }
6417
6418 typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6419 };
6420
6421
6422 struct ToUpperTraits {
6423 typedef unibrow::ToUppercase UnibrowConverter;
6424
6425 typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6426 };
6427 6406
6428 } // namespace 6407 } // namespace
6429 6408
6430 6409
6431 template <typename ConvertTraits> 6410 template <class Converter>
6432 MUST_USE_RESULT static MaybeObject* ConvertCase( 6411 MUST_USE_RESULT static MaybeObject* ConvertCase(
6433 Arguments args, 6412 Arguments args,
6434 Isolate* isolate, 6413 Isolate* isolate,
6435 unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) { 6414 unibrow::Mapping<Converter, 128>* mapping) {
6436 SealHandleScope shs(isolate); 6415 SealHandleScope shs(isolate);
6437 CONVERT_ARG_CHECKED(String, s, 0); 6416 CONVERT_ARG_CHECKED(String, s, 0);
6438 s = s->TryFlattenGetString(); 6417 s = s->TryFlattenGetString();
6439 6418
6440 const int length = s->length(); 6419 const int length = s->length();
6441 // Assume that the string is not empty; we need this assumption later 6420 // Assume that the string is not empty; we need this assumption later
6442 if (length == 0) return s; 6421 if (length == 0) return s;
6443 6422
6444 // Simpler handling of ASCII strings. 6423 // Simpler handling of ASCII strings.
6445 // 6424 //
6446 // NOTE: This assumes that the upper/lower case of an ASCII 6425 // NOTE: This assumes that the upper/lower case of an ASCII
6447 // character is also ASCII. This is currently the case, but it 6426 // character is also ASCII. This is currently the case, but it
6448 // might break in the future if we implement more context and locale 6427 // might break in the future if we implement more context and locale
6449 // dependent upper/lower conversions. 6428 // dependent upper/lower conversions.
6450 if (s->IsSeqOneByteString()) { 6429 if (s->IsSeqOneByteString()) {
6451 Object* o; 6430 Object* o;
6452 { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length); 6431 { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length);
6453 if (!maybe_o->ToObject(&o)) return maybe_o; 6432 if (!maybe_o->ToObject(&o)) return maybe_o;
6454 } 6433 }
6455 SeqOneByteString* result = SeqOneByteString::cast(o); 6434 SeqOneByteString* result = SeqOneByteString::cast(o);
6456 bool has_changed_character; 6435 bool has_changed_character;
6457 bool is_ascii = ConvertTraits::AsciiConverter::Convert( 6436 bool is_ascii = FastAsciiConvert<Converter>(
6458 reinterpret_cast<char*>(result->GetChars()), 6437 reinterpret_cast<char*>(result->GetChars()),
6459 reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()), 6438 reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()),
6460 length, 6439 length,
6461 &has_changed_character); 6440 &has_changed_character);
6462 // If not ASCII, we discard the result and take the 2 byte path. 6441 // If not ASCII, we discard the result and take the 2 byte path.
6463 if (is_ascii) { 6442 if (is_ascii) {
6464 return has_changed_character ? result : s; 6443 return has_changed_character ? result : s;
6465 } 6444 }
6466 } 6445 }
6467 6446
6447 String::Encoding result_encoding = s->IsOneByteRepresentation()
6448 ? String::ONE_BYTE_ENCODING : String::TWO_BYTE_ENCODING;
6468 Object* answer; 6449 Object* answer;
6469 { MaybeObject* maybe_answer = 6450 { MaybeObject* maybe_answer = ConvertCaseHelper(
6470 ConvertCaseHelper(isolate, s, length, length, mapping); 6451 isolate, s, result_encoding, length, length, mapping);
6471 if (!maybe_answer->ToObject(&answer)) return maybe_answer; 6452 if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6472 } 6453 }
6473 if (answer->IsSmi()) { 6454 if (answer->IsSmi()) {
6474 // Retry with correct length. 6455 int new_length = Smi::cast(answer)->value();
6475 { MaybeObject* maybe_answer = 6456 if (new_length < 0) {
6476 ConvertCaseHelper(isolate, 6457 result_encoding = String::TWO_BYTE_ENCODING;
6477 s, Smi::cast(answer)->value(), length, mapping); 6458 new_length = -new_length;
6478 if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6479 } 6459 }
6460 MaybeObject* maybe_answer = ConvertCaseHelper(
6461 isolate, s, result_encoding, new_length, length, mapping);
6462 if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6480 } 6463 }
6481 return answer; 6464 return answer;
6482 } 6465 }
6483 6466
6484 6467
6485 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) { 6468 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6486 return ConvertCase<ToLowerTraits>( 6469 return ConvertCase(
6487 args, isolate, isolate->runtime_state()->to_lower_mapping()); 6470 args, isolate, isolate->runtime_state()->to_lower_mapping());
6488 } 6471 }
6489 6472
6490 6473
6491 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) { 6474 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6492 return ConvertCase<ToUpperTraits>( 6475 return ConvertCase(
6493 args, isolate, isolate->runtime_state()->to_upper_mapping()); 6476 args, isolate, isolate->runtime_state()->to_upper_mapping());
6494 } 6477 }
6495 6478
6496 6479
6497 static inline bool IsTrimWhiteSpace(unibrow::uchar c) { 6480 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6498 return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff; 6481 return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6499 } 6482 }
6500 6483
6501 6484
6502 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) { 6485 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
(...skipping 3217 matching lines...) Expand 10 before | Expand all | Expand 10 after
9720 CONVERT_LANGUAGE_MODE_ARG(language_mode, 3); 9703 CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9721 ASSERT(args[4]->IsSmi()); 9704 ASSERT(args[4]->IsSmi());
9722 return CompileGlobalEval(isolate, 9705 return CompileGlobalEval(isolate,
9723 args.at<String>(1), 9706 args.at<String>(1),
9724 args.at<Object>(2), 9707 args.at<Object>(2),
9725 language_mode, 9708 language_mode,
9726 args.smi_at(4)); 9709 args.smi_at(4));
9727 } 9710 }
9728 9711
9729 9712
9713 // Allocate a block of memory in the given space (filled with a filler).
9714 // Used as a fall-back for generated code when the space is full.
9730 static MaybeObject* Allocate(Isolate* isolate, 9715 static MaybeObject* Allocate(Isolate* isolate,
9731 int size, 9716 int size,
9732 AllocationSpace space) { 9717 AllocationSpace space) {
9733 // Allocate a block of memory in the given space (filled with a filler). 9718 Heap* heap = isolate->heap();
9734 // Use as fallback for allocation in generated code when the space
9735 // is full.
9736 SealHandleScope shs(isolate);
9737 RUNTIME_ASSERT(IsAligned(size, kPointerSize)); 9719 RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9738 RUNTIME_ASSERT(size > 0); 9720 RUNTIME_ASSERT(size > 0);
9739 Heap* heap = isolate->heap();
9740 RUNTIME_ASSERT(size <= heap->MaxRegularSpaceAllocationSize()); 9721 RUNTIME_ASSERT(size <= heap->MaxRegularSpaceAllocationSize());
9741 Object* allocation; 9722 HeapObject* allocation;
9742 { MaybeObject* maybe_allocation; 9723 { MaybeObject* maybe_allocation = heap->AllocateRaw(size, space, space);
9743 if (space == NEW_SPACE) { 9724 if (!maybe_allocation->To(&allocation)) return maybe_allocation;
9744 maybe_allocation = heap->new_space()->AllocateRaw(size);
9745 } else {
9746 ASSERT(space == OLD_POINTER_SPACE || space == OLD_DATA_SPACE);
9747 maybe_allocation = heap->paged_space(space)->AllocateRaw(size);
9748 }
9749 if (maybe_allocation->ToObject(&allocation)) {
9750 heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9751 }
9752 return maybe_allocation;
9753 } 9725 }
9726 #ifdef DEBUG
9727 MemoryChunk* chunk = MemoryChunk::FromAddress(allocation->address());
9728 ASSERT(chunk->owner()->identity() == space);
9729 #endif
9730 heap->CreateFillerObjectAt(allocation->address(), size);
9731 return allocation;
9754 } 9732 }
9755 9733
9756 9734
9757 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) { 9735 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9758 SealHandleScope shs(isolate); 9736 SealHandleScope shs(isolate);
9759 ASSERT(args.length() == 1); 9737 ASSERT(args.length() == 1);
9760 CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0); 9738 CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9761 return Allocate(isolate, size_smi->value(), NEW_SPACE); 9739 return Allocate(isolate, size_smi->value(), NEW_SPACE);
9762 } 9740 }
9763 9741
(...skipping 1578 matching lines...) Expand 10 before | Expand all | Expand 10 after
11342 // First fill all parameters. 11320 // First fill all parameters.
11343 for (int i = 0; i < scope_info->ParameterCount(); ++i) { 11321 for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11344 Handle<Object> value(i < frame_inspector->GetParametersCount() 11322 Handle<Object> value(i < frame_inspector->GetParametersCount()
11345 ? frame_inspector->GetParameter(i) 11323 ? frame_inspector->GetParameter(i)
11346 : isolate->heap()->undefined_value(), 11324 : isolate->heap()->undefined_value(),
11347 isolate); 11325 isolate);
11348 ASSERT(!value->IsTheHole()); 11326 ASSERT(!value->IsTheHole());
11349 11327
11350 RETURN_IF_EMPTY_HANDLE_VALUE( 11328 RETURN_IF_EMPTY_HANDLE_VALUE(
11351 isolate, 11329 isolate,
11352 SetProperty(isolate, 11330 Runtime::SetObjectProperty(isolate,
11353 target, 11331 target,
11354 Handle<String>(scope_info->ParameterName(i)), 11332 Handle<String>(scope_info->ParameterName(i)),
11355 value, 11333 value,
11356 NONE, 11334 NONE,
11357 kNonStrictMode), 11335 kNonStrictMode),
11358 Handle<JSObject>()); 11336 Handle<JSObject>());
11359 } 11337 }
11360 11338
11361 // Second fill all stack locals. 11339 // Second fill all stack locals.
11362 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { 11340 for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11363 Handle<Object> value(frame_inspector->GetExpression(i), isolate); 11341 Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11364 if (value->IsTheHole()) continue; 11342 if (value->IsTheHole()) continue;
11365 11343
11366 RETURN_IF_EMPTY_HANDLE_VALUE( 11344 RETURN_IF_EMPTY_HANDLE_VALUE(
11367 isolate, 11345 isolate,
11368 SetProperty(isolate, 11346 Runtime::SetObjectProperty(
11369 target, 11347 isolate,
11370 Handle<String>(scope_info->StackLocalName(i)), 11348 target,
11371 value, 11349 Handle<String>(scope_info->StackLocalName(i)),
11372 NONE, 11350 value,
11373 kNonStrictMode), 11351 NONE,
11352 kNonStrictMode),
11374 Handle<JSObject>()); 11353 Handle<JSObject>());
11375 } 11354 }
11376 11355
11377 return target; 11356 return target;
11378 } 11357 }
11379 11358
11380 11359
11381 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate, 11360 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11382 Handle<JSObject> target, 11361 Handle<JSObject> target,
11383 Handle<JSFunction> function, 11362 Handle<JSFunction> function,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
11441 Handle<FixedArray> keys = 11420 Handle<FixedArray> keys =
11442 GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw); 11421 GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11443 if (threw) return Handle<JSObject>(); 11422 if (threw) return Handle<JSObject>();
11444 11423
11445 for (int i = 0; i < keys->length(); i++) { 11424 for (int i = 0; i < keys->length(); i++) {
11446 // Names of variables introduced by eval are strings. 11425 // Names of variables introduced by eval are strings.
11447 ASSERT(keys->get(i)->IsString()); 11426 ASSERT(keys->get(i)->IsString());
11448 Handle<String> key(String::cast(keys->get(i))); 11427 Handle<String> key(String::cast(keys->get(i)));
11449 RETURN_IF_EMPTY_HANDLE_VALUE( 11428 RETURN_IF_EMPTY_HANDLE_VALUE(
11450 isolate, 11429 isolate,
11451 SetProperty(isolate, 11430 Runtime::SetObjectProperty(isolate,
11452 target, 11431 target,
11453 key, 11432 key,
11454 GetProperty(isolate, ext, key), 11433 GetProperty(isolate, ext, key),
11455 NONE, 11434 NONE,
11456 kNonStrictMode), 11435 kNonStrictMode),
11457 Handle<JSObject>()); 11436 Handle<JSObject>());
11458 } 11437 }
11459 } 11438 }
11460 } 11439 }
11461 11440
11462 return target; 11441 return target;
11463 } 11442 }
11464 11443
11465 11444
11466 static Handle<JSObject> MaterializeLocalScope( 11445 static Handle<JSObject> MaterializeLocalScope(
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
11546 11525
11547 // Function context extension. These are variables introduced by eval. 11526 // Function context extension. These are variables introduced by eval.
11548 if (function_context->closure() == *function) { 11527 if (function_context->closure() == *function) {
11549 if (function_context->has_extension() && 11528 if (function_context->has_extension() &&
11550 !function_context->IsNativeContext()) { 11529 !function_context->IsNativeContext()) {
11551 Handle<JSObject> ext(JSObject::cast(function_context->extension())); 11530 Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11552 11531
11553 if (JSReceiver::HasProperty(ext, variable_name)) { 11532 if (JSReceiver::HasProperty(ext, variable_name)) {
11554 // We don't expect this to do anything except replacing 11533 // We don't expect this to do anything except replacing
11555 // property value. 11534 // property value.
11556 SetProperty(isolate, 11535 Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11557 ext, 11536 NONE,
11558 variable_name, 11537 kNonStrictMode);
11559 new_value,
11560 NONE,
11561 kNonStrictMode);
11562 return true; 11538 return true;
11563 } 11539 }
11564 } 11540 }
11565 } 11541 }
11566 } 11542 }
11567 11543
11568 return default_result; 11544 return default_result;
11569 } 11545 }
11570 11546
11571 11547
(...skipping 25 matching lines...) Expand all
11597 Handle<FixedArray> keys = 11573 Handle<FixedArray> keys =
11598 GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw); 11574 GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11599 if (threw) return Handle<JSObject>(); 11575 if (threw) return Handle<JSObject>();
11600 11576
11601 for (int i = 0; i < keys->length(); i++) { 11577 for (int i = 0; i < keys->length(); i++) {
11602 // Names of variables introduced by eval are strings. 11578 // Names of variables introduced by eval are strings.
11603 ASSERT(keys->get(i)->IsString()); 11579 ASSERT(keys->get(i)->IsString());
11604 Handle<String> key(String::cast(keys->get(i))); 11580 Handle<String> key(String::cast(keys->get(i)));
11605 RETURN_IF_EMPTY_HANDLE_VALUE( 11581 RETURN_IF_EMPTY_HANDLE_VALUE(
11606 isolate, 11582 isolate,
11607 SetProperty(isolate, 11583 Runtime::SetObjectProperty(isolate, closure_scope, key,
11608 closure_scope, 11584 GetProperty(isolate, ext, key),
11609 key, 11585 NONE,
11610 GetProperty(isolate, ext, key), 11586 kNonStrictMode),
11611 NONE,
11612 kNonStrictMode),
11613 Handle<JSObject>()); 11587 Handle<JSObject>());
11614 } 11588 }
11615 } 11589 }
11616 11590
11617 return closure_scope; 11591 return closure_scope;
11618 } 11592 }
11619 11593
11620 11594
11621 // This method copies structure of MaterializeClosure method above. 11595 // This method copies structure of MaterializeClosure method above.
11622 static bool SetClosureVariableValue(Isolate* isolate, 11596 static bool SetClosureVariableValue(Isolate* isolate,
(...skipping 10 matching lines...) Expand all
11633 isolate, scope_info, context, variable_name, new_value)) { 11607 isolate, scope_info, context, variable_name, new_value)) {
11634 return true; 11608 return true;
11635 } 11609 }
11636 11610
11637 // Properties from the function context extension. This will 11611 // Properties from the function context extension. This will
11638 // be variables introduced by eval. 11612 // be variables introduced by eval.
11639 if (context->has_extension()) { 11613 if (context->has_extension()) {
11640 Handle<JSObject> ext(JSObject::cast(context->extension())); 11614 Handle<JSObject> ext(JSObject::cast(context->extension()));
11641 if (JSReceiver::HasProperty(ext, variable_name)) { 11615 if (JSReceiver::HasProperty(ext, variable_name)) {
11642 // We don't expect this to do anything except replacing property value. 11616 // We don't expect this to do anything except replacing property value.
11643 SetProperty(isolate, 11617 Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11644 ext, 11618 NONE,
11645 variable_name, 11619 kNonStrictMode);
11646 new_value,
11647 NONE,
11648 kNonStrictMode);
11649 return true; 11620 return true;
11650 } 11621 }
11651 } 11622 }
11652 11623
11653 return false; 11624 return false;
11654 } 11625 }
11655 11626
11656 11627
11657 // Create a plain JSObject which materializes the scope for the specified 11628 // Create a plain JSObject which materializes the scope for the specified
11658 // catch context. 11629 // catch context.
11659 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate, 11630 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
11660 Handle<Context> context) { 11631 Handle<Context> context) {
11661 ASSERT(context->IsCatchContext()); 11632 ASSERT(context->IsCatchContext());
11662 Handle<String> name(String::cast(context->extension())); 11633 Handle<String> name(String::cast(context->extension()));
11663 Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX), 11634 Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11664 isolate); 11635 isolate);
11665 Handle<JSObject> catch_scope = 11636 Handle<JSObject> catch_scope =
11666 isolate->factory()->NewJSObject(isolate->object_function()); 11637 isolate->factory()->NewJSObject(isolate->object_function());
11667 RETURN_IF_EMPTY_HANDLE_VALUE( 11638 RETURN_IF_EMPTY_HANDLE_VALUE(
11668 isolate, 11639 isolate,
11669 SetProperty(isolate, 11640 Runtime::SetObjectProperty(isolate, catch_scope, name, thrown_object,
11670 catch_scope, 11641 NONE,
11671 name, 11642 kNonStrictMode),
11672 thrown_object,
11673 NONE,
11674 kNonStrictMode),
11675 Handle<JSObject>()); 11643 Handle<JSObject>());
11676 return catch_scope; 11644 return catch_scope;
11677 } 11645 }
11678 11646
11679 11647
11680 static bool SetCatchVariableValue(Isolate* isolate, 11648 static bool SetCatchVariableValue(Isolate* isolate,
11681 Handle<Context> context, 11649 Handle<Context> context,
11682 Handle<String> variable_name, 11650 Handle<String> variable_name,
11683 Handle<Object> new_value) { 11651 Handle<Object> new_value) {
11684 ASSERT(context->IsCatchContext()); 11652 ASSERT(context->IsCatchContext());
(...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after
12682 // Skip if "arguments" is already taken. 12650 // Skip if "arguments" is already taken.
12683 if (!function->shared()->is_function() || 12651 if (!function->shared()->is_function() ||
12684 JSReceiver::HasLocalProperty(target, 12652 JSReceiver::HasLocalProperty(target,
12685 isolate->factory()->arguments_string())) { 12653 isolate->factory()->arguments_string())) {
12686 return target; 12654 return target;
12687 } 12655 }
12688 12656
12689 // FunctionGetArguments can't throw an exception. 12657 // FunctionGetArguments can't throw an exception.
12690 Handle<JSObject> arguments = Handle<JSObject>::cast( 12658 Handle<JSObject> arguments = Handle<JSObject>::cast(
12691 Accessors::FunctionGetArguments(function)); 12659 Accessors::FunctionGetArguments(function));
12692 SetProperty(isolate, 12660 Runtime::SetObjectProperty(isolate, target,
12693 target, 12661 isolate->factory()->arguments_string(),
12694 isolate->factory()->arguments_string(), 12662 arguments,
12695 arguments, 12663 ::NONE,
12696 ::NONE, 12664 kNonStrictMode);
12697 kNonStrictMode);
12698 return target; 12665 return target;
12699 } 12666 }
12700 12667
12701 12668
12702 // Compile and evaluate source for the given context. 12669 // Compile and evaluate source for the given context.
12703 static MaybeObject* DebugEvaluate(Isolate* isolate, 12670 static MaybeObject* DebugEvaluate(Isolate* isolate,
12704 Handle<Context> context, 12671 Handle<Context> context,
12705 Handle<Object> context_extension, 12672 Handle<Object> context_extension,
12706 Handle<Object> receiver, 12673 Handle<Object> receiver,
12707 Handle<String> source) { 12674 Handle<String> source) {
(...skipping 2130 matching lines...) Expand 10 before | Expand all | Expand 10 after
14838 // Handle last resort GC and make sure to allow future allocations 14805 // Handle last resort GC and make sure to allow future allocations
14839 // to grow the heap without causing GCs (if possible). 14806 // to grow the heap without causing GCs (if possible).
14840 isolate->counters()->gc_last_resort_from_js()->Increment(); 14807 isolate->counters()->gc_last_resort_from_js()->Increment();
14841 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 14808 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
14842 "Runtime::PerformGC"); 14809 "Runtime::PerformGC");
14843 } 14810 }
14844 } 14811 }
14845 14812
14846 14813
14847 } } // namespace v8::internal 14814 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/runtime.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698